Esempio n. 1
0
    def compress_project(self, set_hash=True):
        Log("Compressing project..", "notice")

        # Clean out temp project if it exists
        Log("Cleaning out temp folder")
        Folder.delete(self.get_temp_dir())

        # Extract cache if it exists
        if self.is_cached():
            Tar.extract(filepath=self.get_cache_file(),
                        destination=self.get_temp_dir().parent)
        else:
            Folder.create(self.get_temp_dir())

        # Create folders if they dont exist
        self.create_required_folders(temp=True, clean=False)

        # Copy from 'extracted_songs' to 'temp'
        if not self.move_extracted_song_to_temp():
            Log("Could not move project from 'extracted_songs' to 'temp'..",
                "warning")
            Log.press_enter()
            return False

        # Compress project to *.lof
        Tar.compress(folderpath=self.get_temp_dir(),
                     destination=self.get_cache_file())

        if set_hash:
            # Set new local hash
            Hash.set_project_hash(self, Hash.create_hash_from_project(self))

        return True
Esempio n. 2
0
    def move_temp_to_extracted_songs(self):
        # Convert mp3's to wav's
        for location in ["Media", "Bounces"]:
            Log(f'Converting "{location}" mp3\'s to wav\'s')
            if not Audio.folder_to_wav(self.get_temp_dir() / location,
                                       self.get_root_dir() / location):
                return False

            # Copy over dummy.json
            Log(f'Copying over "{location}" dummy.json')
            if self.get_dummy_db(location, temp=True).exists():
                File.recursive_overwrite(
                    self.get_dummy_db(location, temp=True),
                    self.get_dummy_db(location, temp=False),
                )

        # Copy over the previous mixdowns
        Log("Copying over 'Mixdown' mp3's")
        Folder.copy(self.get_temp_dir() / "Mixdown",
                    self.get_root_dir() / "Mixdown")

        # Copy over the song file
        Log("Copying over Studio One project file")
        File.recursive_overwrite(self.get_song_file(temp=True),
                                 self.get_song_file(temp=False))
        File.recursive_overwrite(
            self.get_song_file(temp=True),
            self.get_song_file(version="original", temp=False))

        return True
Esempio n. 3
0
    def initialize():
        Database.cloud_id = Database.get_cloud_id()

        # Clean out temp folder
        Folder.clear_temp()

        # Download a fresh version of the database
        Database.refresh()
Esempio n. 4
0
    def delete_project(self):
        options = []
        if self.is_local():
            options.append("local")
        if self.is_remote():
            options.append("remote")
        if self.is_local() and self.is_remote():
            options.append("both")
        options.append("back")

        dialog = Dialog(
            title=f'Deleting Project "{self.entry.name}"',
            body=[
                f'Would you like to delete the local or remote version?',
                f'\n',
                f'\n',
                f'Warning: This is not reversible!',
            ])

        ans = dialog.get_mult_choice(options)

        if ans == "back":
            return True

        if ans == "local" or ans == "both":
            # Remove extracted folder and cached file
            File.delete(self.get_cache_file())
            Folder.delete(self.get_root_dir())

            # Remove hash from local db
            Hash.remove_project_hash(self)

            Menu.notice = f'Project "{self.entry.name}" deleted locally!'

        if ans == "remote" or ans == "both":
            if self.is_remote():
                # Delete compressed file
                project_id = self.entry.data["id"]
                if project_id:
                    Drive.delete(project_id)

                # Delete folder with scratch tracks and mixdowns
                folder_id = Drive.get_id(self.entry.name)
                if folder_id:
                    Drive.delete(folder_id)

                # Remove entry from remote db
                self.entry.destroy()

                Menu.notice = f'Project "{self.entry.name}" deleted remotely!'

        if ans == "both":
            Menu.notice = f'Project "{self.entry.name}" completely deleted!'

        return True
Esempio n. 5
0
 def remove_dummy_files(self):
     # Remove any wav files that are 0 bytes in size
     for folder in FOLDERS:
         folder = self.get_root_dir() / folder
         wavs = Folder.ls_files(folder, "wav")
         for wav in wavs:
             if wav.exists() and wav.stat().st_size == 0:
                 wav.unlink()
Esempio n. 6
0
def clean_out_cache():
    dialog = Dialog(
        title="Clean Out Cache",
        body=[
            f'This will remove all pre-downloaded *.lof compressed files.',
            f'\n',
            f'\n',
            f'This should not harm any saved songs you have! This only',
            f'removes the pre-downloaded compressed cache.',
            f'\n',
            f'\n',
        ])

    if dialog.confirm():
        Folder.clear(f'compressed_songs')
        Menu.notice = "Cache is cleaned out!"

    return True
Esempio n. 7
0
    def to_wav(self, folderpath):
        folderpath = Path(folderpath)
        Folder.create(folderpath)

        mp3 = self.filepath
        wav = Path(f'{folderpath.absolute()}/{mp3.stem}.wav')
        stem, num, ext = File.split_name(wav.name)

        if wav.is_file():
            # File already exists locally, do not do anything
            Log(f'File "{wav.name}" already exists, keeping local file.')
            return True

        Run.ffmpeg(args="-i",
                   source=mp3.absolute(),
                   destination=wav.absolute(),
                   codec="-c:a pcm_s24le")
        return True
Esempio n. 8
0
    def folder_to_mp3(folderpath, destination):
        folderpath = Path(folderpath)
        destination = Path(destination)
        wavs = glob(f"{folderpath.absolute()}/*.wav")
        username_ignore = False

        Folder.create(destination)

        for wav in wavs:
            result = Audio(wav).to_mp3(folderpath=destination,
                                       username_ignore=username_ignore)

            if isinstance(result, dict):
                username_ignore = result["username_ignore"]
            else:
                if not result:
                    return False

        return True
Esempio n. 9
0
    def extract_project(self):
        Log("Extracting project..")

        # Create required folders in 'extracted_songs'
        self.create_required_folders()

        # Extract cache to 'temp' folder
        Log("Extracting project")
        Tar.extract(self.get_cache_file(), self.get_temp_dir().parent)

        # Copy and convert from 'temp' to 'extracted_songs'
        if not self.move_temp_to_extracted_songs():
            # If function fails, remove broken extracted project
            # to prevent issues trying again.
            Folder.delete(self.get_root_dir())
            Log("Could not move project from 'temp' to 'extracted_songs'..",
                "warning")
            Log.press_enter()
            return False

        return True
Esempio n. 10
0
def clear_all_local_projects():
    result = Dialog("Clear Local Projects", [
        f'This will clear all locally cached projects to save',
        f'space on your hard drive.',
        f'\n',
        f'This will NOT:',
        f'\n',
        f'  - Delete any songs on the cloud',
        f'\n',
        f'  - Delete any dirty projects on your computer',
        f'\n',
        f'    that have not been uploaded yet',
        f'\n',
        f'  - Remove any projects that have never been',
        f'\n',
        f'    uploaded to the cloud yet',
        f'\n',
    ]).confirm()

    if result:
        for project in ProjectIndex.get_all_projects():
            if not project.is_dirty() and project.is_remote():
                # Just in case we have it locked
                project.remove_lock()

                # Remove extracted folder and cached file
                File.delete(project.get_cache_file())
                Folder.delete(project.get_root_dir())

                # Remove hash from local db
                Hash.remove_project_hash(project)

            Menu.notice = f'Local projects cleared!'
    else:
        Menu.notice = f'No local projects were cleared..'
    return True
Esempio n. 11
0
    def duplicate(self):
        if not self.dialog_copy_confirm():
            return False

        new_name = self.dialog_copy_new_name()
        new_path = self.get_root_dir().parent / new_name

        Log(f'Duplicating "{self.entry.name}" to "{new_name}"..')

        Folder.copy(self.get_root_dir(), new_path)

        Log(f'Renaming song file', 'sub')
        File.rename(new_path / (self.get_song_file().name),
                    new_path / f'{new_name}.song')

        if self.get_song_file(version="original").exists():
            Log(f'Renaming *original song file', 'sub')
            File.rename(
                new_path / (self.get_song_file(version="original").name),
                new_path / f'{new_name}_original.song')

        Menu.notice = f'Created Project "{new_name}"!'

        return True
Esempio n. 12
0
    def dialog_copy_new_name(self):
        dialog = Dialog(
            title=f'Make Duplicate of "{self.entry.name}"',
            body="Please enter a new name for your duplicate project.")

        new_name = dialog.get_result("New Name").lower()
        project_names = [
            x.name.lower()
            for x in Folder.ls_folders(self.get_root_dir().parent)
        ]

        if not new_name in project_names:
            return new_name

        Log("That project name already exists.. Please try again!")
        Log.press_enter()

        return self.dialog_copy_new_name()
Esempio n. 13
0
    def set_dummy_files(self):
        # double check that the dummy.json files exist
        self.create_dummy_json()

        for folder in FOLDERS:
            folder = self.get_root_dir() / folder
            dummy_json = folder / "dummy.json"
            data = File.get_json(dummy_json)
            wavs = Folder.ls_files(folder, "wav")

            # Lets find the max wav numbers
            for wav in wavs:
                file_stem, num, ext = File.split_name(wav)

                if not file_stem in data["max"]:
                    data["max"][file_stem] = num
                else:
                    if num > data["max"][file_stem]:
                        data["max"][file_stem] = num

            # Now lets create the dummy files if they don't already exist
            for file_stem in data["max"]:
                num = data["max"][file_stem]

                for i in range(num):
                    if i == 0:
                        path = folder / f'{file_stem}.wav'
                    else:
                        path = folder / f'{file_stem}({i}).wav'

                    path.touch()

            # Lets also get rid of the "dummy" key that is unused now
            if "dummy" in data:
                data.pop("dummy")

            # Lastly, lets update the dummy.json file
            File.set_json(dummy_json, data)
Esempio n. 14
0
def exit():
    Folder.clear_temp()
    # 0 = there was a problem
    # 1 = exit gracefully
    sys.exit(1)
Esempio n. 15
0
    def move_extracted_song_to_temp(self):
        # Make sure we don't have any dummy files
        self.remove_dummy_files()

        for location in ["Media", "Bounces"]:
            # Remove unused cached audio from location
            # Garbage collector for unused audio files
            mp3s = Folder.ls_files(self.get_temp_dir() / location, "mp3")
            wav_names = [
                x.stem
                for x in Folder.ls_files(self.get_root_dir() / location, "wav")
            ]
            for mp3 in mp3s:
                if mp3.stem not in wav_names:
                    File.delete(mp3)

            # Convert and move wavs to mp3s
            Log(f'Converting "{location}" wav\'s to mp3\'s')
            if not Audio.folder_to_mp3(self.get_root_dir() / location,
                                       self.get_temp_dir() / location):
                return False

            # Copy over dummy.json
            Log(f'Copying over "{location}" dummy.json')
            if self.get_dummy_db(location, temp=False).exists():
                File.recursive_overwrite(
                    self.get_dummy_db(location, temp=False),
                    self.get_dummy_db(location, temp=True),
                )

        # Upload scratch files and mixdowns to the cloud
        mp3s = Folder.ls_files(self.get_temp_dir() / "Media", "mp3",
                               "Scratch*")
        mp3s.extend(
            Folder.ls_files(self.get_temp_dir() / "Media", "mp3", "SCRATCH*"))
        mp3s.extend(Folder.ls_files(self.get_root_dir() / "Mixdown", "mp3"))

        for mp3 in mp3s:
            mix_folder_id = Drive.get_id(self.entry.name)

            if not Drive.get_id(mp3.name, mix_folder_id):
                Log(f'Uploading "{mp3.name}" to the cloud', "sub")
                mp3_id = Drive.upload(filepath=mp3,
                                      mimeType=Drive.mimeType["mp3"],
                                      parent=mix_folder_id)

                audio_type = "Scratch" if mp3.parent.name == "Media" else "#MIXDOWN#"
                Slack.send_link(
                    link_name=
                    f'{audio_type} for {self.entry.name}, "{mp3.name}"',
                    ID=mp3_id)
            else:
                Log(f'Audio file "{mp3.name}" already exists on the cloud!',
                    "sub")

        # Copy over mixdowns to temp
        Log("Copying over 'Mixdown' mp3's")
        Folder.copy(self.get_root_dir() / "Mixdown",
                    self.get_temp_dir() / "Mixdown")

        # Lastly, copy over the song file
        File.recursive_overwrite(self.get_song_file(temp=False),
                                 self.get_song_file(temp=True))

        return True
Esempio n. 16
0
 def get_local_projects():
     local = Folder.ls_folders(EXTRACTED)
     return [Project(x.name) for x in local]
Esempio n. 17
0
import traceback,sys
from src.Slack import Slack
from src.Update import Update
from src.Settings import Settings
from src.TERMGUI.Log import Log
from src.FileManagement.Folder import Folder
from src.menus.menu_main import menu_main

# MAIN FUNCTION
if __name__ == '__main__':

    # Create file structure if it doesn't exist
    Folder.create("compressed_songs")
    Folder.create("extracted_songs")
    Folder.create("temp")
    Folder.create("templates")

    # Create settings file if it doesn't exist
    Settings.create()

    # Start main menu
    try:
        menu_main()
    except Exception as e:
        Log(traceback.format_exc(),"warning")
        # 0 = there was a problem
        # 1 = exit gracefully
        sys.exit(0)
Esempio n. 18
0
    def create_required_folders(self, temp=False, clean=True):
        # 'temp=True'  will focus on the temp/<song> directory
        # 'temp=False' will focus on the extracted_songs/<song> directory
        # 'clean=True' will delete the folders first, then recreate them

        # Need to make sure these folders exist
        Log("Creating necessary folders")

        if temp:
            # Clean out temp dir
            if clean:
                Folder.delete(self.get_temp_dir())
            Folder.create(self.get_temp_dir())
        else:
            # Create new extracted dir, remove if exists
            if clean:
                Folder.delete(self.get_root_dir())
            Folder.create(self.get_root_dir())

        for location in ["Media", "Bounces", "Mixdown"]:
            if temp:
                Folder.create(self.get_temp_dir() / location)
            Folder.create(self.get_root_dir() / location)

        return True