<commit_before># Scalpel sound editor (http://scalpelsound.online.fr)
# Copyright 2009 (C) <NAME> <<EMAIL>>
# Licensed under the Revised BSD License.

import edit
import clipboard
from player import Player
from event import Signal
import effect
import app
import traceback

class Controller(object):

    def __init__(self, sound, player, graph, selection):
        self._player = player
        self._graph = graph
        self._selection = selection
        self._sound = sound
        self.filename_changed = Signal()
        self.error = Signal()

    def new(self):
        app.open_()

    def _report_exception(method):
        """Method decorator.

        Call the self.error signal when an exception was raised in the
        decorated method.

        """
        def wrapper(self, *args, **kwargs):
            result = None
            try:
                result = method(self, *args, **kwargs)
            except Exception, e:
                self.error("Error", str(e))
                traceback.print_exc()
            return result

        wrapper.__name__ = method.__name__
        wrapper.__doc__ = method.__doc__
        return wrapper

    @_report_exception
    def open(self, filename):
        if self._sound.is_fresh():
            self.load_sound(filename)
        else:
            app.open_(filename)

    @_report_exception
    def load_sound(self, filename):
        self._player.stop()
        self._sound = edit.Sound(filename)
        self._graph.set_sound(self._sound)
        self._player.set_sound(self._sound)
        self._selection.unselect()
        self.filename_changed()

    @_report_exception
    def save(self):
        self._sound.save()

    @_report_exception
    def save_as(self, filename):
        self._sound.save_as(filename)
        self.filename_changed()

    @_report_exception
    def save_selection_as(self, filename):
        sound = edit.Sound()
        if not self._selection.selected():
            raise Exception("There is no selection.")
        start, end = self._selection.get()
        sound.frames = self._sound.copy(start, end)
        sound.samplerate = self._sound.samplerate
        sound.save_as(filename)

    def close(self, force=False):
        sound = self._sound
        if not sound.is_saved() and not sound.is_fresh() and not force:
            raise FileNotSaved
        self._player.stop()

    def play(self):
        start, end = self._selection.get()
        if not self._selection.selected():
            end = len(self._sound.frames)
        self._player.start = start
        self._player.end = end
        self._player.thread_play()

    def stop(self):
        self._player.stop()

    def toggle_play(self):
        if self._player._playing:
            self.stop()
        else:
            self.play()

    def goto_start(self):
        self._selection.set(0, 0)
        self._graph.move_to(0)

    def goto_end(self):
        end = len(self._sound.frames)
        self._selection.set(end, end)

    def cut(self):
        start, end = self._selection.get()
        self._selection.start = start
        self._selection.end = start
        clipboard.clip = self._sound.cut(start, end)
        
    def copy(self):
        start, end = self._selection.get()
        clipboard.clip = self._sound.copy(start, end)
        
    @_report_exception
    def paste(self):
        start, end = self._selection.get()
        was_zoomed_out_full = self._graph.is_zoomed_out_full()
        self._sound.paste(start, end, clipboard.clip)
        self._selection.set(start, start + len(clipboard.clip))
        if was_zoomed_out_full:
            self._graph.zoom_out_full()

    @_report_exception
    def mix(self):
        start, end = self._selection.get()
        self._sound.mix(start, end, clipboard.clip)
        # FIXME: should be dealt with in Sound.
        if start == end:
            l = len(clipboard.clip)
        else:
            l = min(end - start, len(clipboard.clip))
        self._selection.set(start, start + l)

    def trim(self):
        pass

    def undo(self):
        self._sound.undo()
        self.fix_selection()

    def redo(self):
        self._sound.redo()
        self.fix_selection()

    def fix_selection(self):
        start, end = self._selection.get()
        n = len(self._sound.frames)
        if end > n:
            # Selection has become invalid.
            start = min(start, n)
            end = n
            self._selection.set(start, end)

    def select_all(self):
        self._selection.select_all()

    def zoom_out(self):
        self._graph.zoom_out()

    def zoom_in(self):
        self._graph.zoom_in()

    def zoom_fit(self):
        if self._selection.selected():
            start, end = self._selection.get()
            self._graph.set_view(start, end)
        else:
            self._graph.zoom_out_full()

    @_report_exception
    def effect(self, name):
        if self._selection.selected():
            start, end = self._selection.get()
        else:
            start = 0
            end = len(self._sound.frames)
        fx = effect.effects[name]
        return fx(self._sound, start, end)

    def filename(self):
        return self._sound.filename

class FileNotSaved: pass

def test_Controller():
    from mock import Fake
    
    # Test opening a file
    ctrl = Controller(Fake(), Fake(), Fake(), Fake())<commit_msg>Make FileNotSaved a proper Exception.<commit_after># Scalpel sound editor (http://scalpelsound.online.fr)
# Copyright 2009 (C) <NAME> <<EMAIL>>
# Licensed under the Revised BSD License.

import edit
import clipboard
from player import Player
from event import Signal
import effect
import app
import traceback

class Controller(object):

    def __init__(self, sound, player, graph, selection):
        self._player = player
        self._graph = graph
        self._selection = selection
        self._sound = sound
        self.filename_changed = Signal()
        self.error = Signal()

    def new(self):
        app.open_()

    def _report_exception(method):
        """Method decorator.

        Call the self.error signal when an exception was raised in the
        decorated method.

        """
        def wrapper(self, *args, **kwargs):
            result = None
            try:
                result = method(self, *args, **kwargs)
            except Exception, e:
                self.error("Error", str(e))
                traceback.print_exc()
            return result

        wrapper.__name__ = method.__name__
        wrapper.__doc__ = method.__doc__
        return wrapper

    @_report_exception
    def open(self, filename):
        if self._sound.is_fresh():
            self.load_sound(filename)
        else:
            app.open_(filename)

    @_report_exception
    def load_sound(self, filename):
        self._player.stop()
        self._sound = edit.Sound(filename)
        self._graph.set_sound(self._sound)
        self._player.set_sound(self._sound)
        self._selection.unselect()
        self.filename_changed()

    @_report_exception
    def save(self):
        self._sound.save()

    @_report_exception
    def save_as(self, filename):
        self._sound.save_as(filename)
        self.filename_changed()

    @_report_exception
    def save_selection_as(self, filename):
        sound = edit.Sound()
        if not self._selection.selected():
            raise Exception("There is no selection.")
        start, end = self._selection.get()
        sound.frames = self._sound.copy(start, end)
        sound.samplerate = self._sound.samplerate
        sound.save_as(filename)

    def close(self, force=False):
        sound = self._sound
        if not sound.is_saved() and not sound.is_fresh() and not force:
            raise FileNotSaved
        self._player.stop()

    def play(self):
        start, end = self._selection.get()
        if not self._selection.selected():
            end = len(self._sound.frames)
        self._player.start = start
        self._player.end = end
        self._player.thread_play()

    def stop(self):
        self._player.stop()

    def toggle_play(self):
        if self._player._playing:
            self.stop()
        else:
            self.play()

    def goto_start(self):
        self._selection.set(0, 0)
        self._graph.move_to(0)

    def goto_end(self):
        end = len(self._sound.frames)
        self._selection.set(end, end)

    def cut(self):
        start, end = self._selection.get()
        self._selection.start = start
        self._selection.end = start
        clipboard.clip = self._sound.cut(start, end)
        
    def copy(self):
        start, end = self._selection.get()
        clipboard.clip = self._sound.copy(start, end)
        
    @_report_exception
    def paste(self):
        start, end = self._selection.get()
        was_zoomed_out_full = self._graph.is_zoomed_out_full()
        self._sound.paste(start, end, clipboard.clip)
        self._selection.set(start, start + len(clipboard.clip))
        if was_zoomed_out_full:
            self._graph.zoom_out_full()

    @_report_exception
    def mix(self):
        start, end = self._selection.get()
        self._sound.mix(start, end, clipboard.clip)
        # FIXME: should be dealt with in Sound.
        if start == end:
            l = len(clipboard.clip)
        else:
            l = min(end - start, len(clipboard.clip))
        self._selection.set(start, start + l)

    def trim(self):
        pass

    def undo(self):
        self._sound.undo()
        self.fix_selection()

    def redo(self):
        self._sound.redo()
        self.fix_selection()

    def fix_selection(self):
        start, end = self._selection.get()
        n = len(self._sound.frames)
        if end > n:
            # Selection has become invalid.
            start = min(start, n)
            end = n
            self._selection.set(start, end)

    def select_all(self):
        self._selection.select_all()

    def zoom_out(self):
        self._graph.zoom_out()

    def zoom_in(self):
        self._graph.zoom_in()

    def zoom_fit(self):
        if self._selection.selected():
            start, end = self._selection.get()
            self._graph.set_view(start, end)
        else:
            self._graph.zoom_out_full()

    @_report_exception
    def effect(self, name):
        if self._selection.selected():
            start, end = self._selection.get()
        else:
            start = 0
            end = len(self._sound.frames)
        fx = effect.effects[name]
        return fx(self._sound, start, end)

    def filename(self):
        return self._sound.filename

class FileNotSaved(Exception): pass

def test_Controller():
    from mock import Fake
    
    # Test opening a file
    ctrl = Controller(Fake(), Fake(), Fake(), Fake())
{'fraction_non_alphanumeric': 0.10570609451586054, 'fraction_numerical': 0.001479700360676963, 'mean_word_length': 2.0291316526610643, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2051990', 'n_tokens_mistral': 3174, 'n_tokens_neox': 3079, 'n_words': 733}