コード例 #1
0
ファイル: podcasttools.py プロジェクト: sisoe24/PodcastTool
    def course_name(self):
        """Get the full course name of the parsed file.

        Returns:
            [str] - - the full name of the course name.

        """
        code = self._splitted_name[0]
        LOGGER.debug('course code from file: %s', code)

        # the code is always the first 3 strings in the name
        course_code, edition = regex.sub(r'([A-Z]{3})([A-Z]{1,3}|\d{1,3})',
                                         r'\1 \2', code).split(' ')

        LOGGER.debug('codice corso, edizione: %s, %s', course_code, edition)

        courses_names = util.catalog_names("corsi")
        course_info = courses_names[course_code]
        self._course_path = f"{course_info['course_path']}/{code}"

        course = course_info['course_name']
        LOGGER.debug('get complete course name: %s', course)

        self.html_page['course_name'] = course

        return course
コード例 #2
0
def get_similar_words(wrong_name: str, catalog: str) -> str:
    """If user writes the wrong name try suggesting valid alternative.

    Arguments:
        wrong_name {str} - the not found word that the user has written
        catalog {str} - the type of list in where to search:
                        c = courses (list of courses)
                        t = teachers (list of teachers)
    Returns:
        [str] -- return the correct word choosen by the user.

    """
    if catalog == 'c':
        check_list = util.catalog_names('corsi').keys()
    elif catalog == 't':
        check_list = util.catalog_names('docenti').keys()

    similar_name = get_close_matches(wrong_name, check_list, cutoff=0.6)
    possibile_names = [i for i in similar_name]
    choice = f"- {wrong_name} -> {possibile_names}"
    return choice
コード例 #3
0
    def _check_course_errors(self, filename: str, line_num: int):
        """Check for errors in the course name.

        Arguments:
            filename {str} - filename to parse for errors.
            line_num {int} - the current line number in the text widget.
        """
        course_match = regex.search(r'^[A-Z]{3}', filename, regex.I)
        tag = f"c{line_num}"
        if course_match.group() not in util.catalog_names('corsi').keys():
            self._tag_errors(course_match.span(), line_num, tag)
            self.log_frame.display_msg(
                get_similar_words(course_match.group(), "c"),
                self._tag_color(tag))
        else:
            self._tag_remove(tag)
コード例 #4
0
ファイル: podcasttools.py プロジェクト: sisoe24/PodcastTool
    def teacher_name(self):
        """Get the full name of the teacher.

        Returns:
            [str] - - full name of the teacher abbreviation code.

        """
        short_name = '_'.join(self._splitted_name[2:4])
        LOGGER.debug('teacher name from file: %s', short_name)

        teacher_names = util.catalog_names("docenti")
        full_name = teacher_names[short_name]
        LOGGER.debug('teacher full name: %s', full_name)

        self.html_page['teacher_name'] = full_name
        return full_name
コード例 #5
0
    def _check_teacher_errors(self, filename, line_num):
        """Check for errors in the teacher name.

        Arguments:
            filename {str} - filename to parse for errors.
            line_num {int} - the current line number in the text widget.
        """
        teacher_match = regex.search(r'(?<=_)[A-Z]_[A-Za-z]+', filename)

        tag = f"t{line_num}"

        if teacher_match.group() not in util.catalog_names('docenti').keys():
            self._tag_errors(teacher_match.span(), line_num, tag)
            self.log_frame.display_msg(
                get_similar_words(teacher_match.group(), "t"),
                self._tag_color(tag))
        else:
            self._tag_remove(tag)
コード例 #6
0
ファイル: podcasttools.py プロジェクト: sisoe24/PodcastTool
        def _split_raw_podcast():
            watermark = util.catalog_names()["watermark"]
            LOGGER.debug("watermark audio: %s", watermark)

            podcast = pydub.AudioSegment.from_wav(self.abspath)
            cuts = (util.calculate_cuts(len(podcast))
                    if not num_cuts else num_cuts)
            LOGGER.debug("splitting podcast in: [%s] parts", cuts)

            cut_each = math.ceil(len(podcast) / cuts)
            podcast_parts = podcast[::cut_each]

            n_parts = len(self._audio_intro)
            for part in podcast_parts:
                export_name = f"{tmp_dir}/{n_parts}-podcast-segment.wav"
                part.export(export_name,
                            parameters=["-ar", sample_rate],
                            format="wav",
                            bitrate=bitrate)

                self._audio_intro.append("podcast_segment")
                self._audio_intro.append(watermark)

                n_parts += 2
コード例 #7
0
ファイル: audio_frame.py プロジェクト: sisoe24/PodcastTool
class AudioIntro(tk.Frame):
    """Audio intro modification section of the gui."""
    _catalog = util.catalog_names()
    _new_audio = []
    list_len = len(_catalog["intro"])

    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)

        self.audio_catalog = self._catalog

        self._audio_frame = ttk.Frame(self,)
        self._audio_frame.grid(column=0, row=0)

        self._audio_list_frame = ttk.LabelFrame(
            self._audio_frame, text="Audio intro", padding=1)
        self._audio_list_frame.grid(column=0, row=0)

        self.create_combobox()

        ttk.Button(self._audio_list_frame, text="aggiungi casella",
                   command=self.add_combobox).grid(column=1, row=20)
        ttk.Button(self._audio_list_frame, text="Salva nuova lista",
                   command=self.new_intro).grid(column=1, row=20, sticky=tk.E,
                                                pady=5, padx=5)

        water_frame = ttk.LabelFrame(self._audio_frame, text="Watermark",
                                     padding=1)
        water_frame.grid(column=0, row=3, sticky=tk.W)

        self.watermark = ttk.Combobox(water_frame, width=42)
        self.watermark.grid(column=0, row=4, sticky=tk.E)
        self.watermark.set(self._catalog["watermark"])

        save_watermark = ttk.Button(water_frame,
                                    text="Salva nuovo watermark",
                                    command=self.new_watermark)
        save_watermark.grid(column=0, row=5, sticky=tk.E, pady=5, padx=5)

        create_frame = ttk.LabelFrame(
            self._audio_frame, text="Crea text audio", padding=1)
        create_frame.grid(column=0, row=6, sticky=tk.W)

        ttk.Label(create_frame, text="text:").grid()

        self.text_entry = ttk.Entry(create_frame, width=40)
        self.text_entry.grid(column=1, row=0)

        ttk.Button(create_frame, text="Crea audio",
                   command=self.text_to_audio).grid(column=1, row=1,
                                                    sticky=tk.E,
                                                    pady=5, padx=5)

        ttk.Label(create_frame, text="lang:").grid(column=0, row=1,
                                                   sticky=tk.W)
        self._lang_select = ttk.Combobox(create_frame, value=["it", "en"],
                                         state="readonly", width=2)
        self._lang_select.grid(column=1, row=1, sticky=tk.W)
        self._lang_select.current(0)

    def text_to_audio(self):
        """Generate text to audio files."""
        ask_user = filedialog.asksaveasfilename()
        if ask_user:
            path, filename = os.path.split(ask_user)
            util.generate_audio(text=self.text_entry.get(),
                                filename=filename, path=path,
                                lang=self._lang_select.get())

    def add_combobox(self):
        """Add new combobox widget if user wants."""
        ttk.Combobox(self._audio_list_frame, value=self.const_vars(),
                     width=40).grid(column=1, row=self.list_len)
        self.list_len += 1

    def create_combobox(self):
        """Create combobox widget from the audio intro list."""
        for index, element in enumerate(self.audio_catalog["intro"]):
            ttk.Label(self._audio_list_frame, text=index +
                      1).grid(column=0, row=index)

            combo = ttk.Combobox(self._audio_list_frame, width=40,
                                 value=self.const_vars())
            combo.grid(column=1, row=index, sticky=tk.W)

            if element not in self.const_vars():
                element = element.replace("_", " ")
            combo.set(element)

    def parse_frame(self):
        """Parse audio list frame for combobox widgets and get their values."""
        for widget in self._audio_list_frame.winfo_children():
            if "combobox" in widget.winfo_name():
                widget_data = widget.get()
                if widget_data:
                    yield widget_data

    def new_audio(self, current_intro):
        """Get the elements in the audio.

        Get the audio list frame and check if there are new names.

        Arguments:
            current_intro [list] - the current audio intro list.
        """
        for name in self.parse_frame():
            if name not in current_intro:
                yield name

    def generate_new_audio(self, audio_list):
        """Gnerate new audio files for the intro.

        Arguments:
            audio_list {list/tuple} - iterable variable to generate new audio
        """
        path = util.get_path("include/audio/new_audio")

        for index, name in enumerate(audio_list, 10):

            msg = f"Generating audio for: {name}"
            ttk.Label(self._audio_frame, text=msg).grid(column=0, row=index)
            self.update()
            util.generate_audio(text=name, path=path)

    def new_intro(self):
        """Check if audio intro was modified."""
        current_catalog = self._catalog["intro"]
        new_catalog = self.audio_catalog["intro"] = list(self.parse_frame())
        new_intro_list = self.new_audio(current_catalog)

        self.compare_current(current_catalog, new_catalog, new_intro_list)

    def new_watermark(self):
        """Check if current watermark was modified."""
        current_watermark = self._catalog["watermark"]
        new_watermark = self.audio_catalog["watermark"] = self.watermark.get()

        self.compare_current(current_watermark, new_watermark, [new_watermark])

    def compare_current(self, current_value, new_value, audio_list):
        """Compare if current_value catalog was modified.
        If yes then create new audio from list and save into catalog.

        Arguments:
            current_value - value of catalog dictionary to be compared
            new_value - value of catalog dictionary to be compared
            audio_list {list} - a list from where to generate the new audio
        """
        if current_value != new_value:
            self.generate_new_audio(audio_list)
            self.save_new()
        else:
            messagebox.showinfo(message="Nessuna modifica?", icon="question")

    def save_new(self):
        """Save modifications in catalog json file."""
        with open(util.catalog_file(), "w") as json_file:
            json.dump(self.audio_catalog, json_file, indent=True)
        messagebox.showinfo(title="Done", message="Done!", icon="info")

    @staticmethod
    def const_vars():
        """Return a list of string placeholders for variables names that
        can be used in the audio intro.
        """
        return ["$VAR{course_name}", "$VAR{teacher_name}",
                "$VAR{lesson_number}", "$VAR{part_number}",
                "$VAR{day}", "$VAR{month}", "$VAR{year}"]
コード例 #8
0
ファイル: podcasttools.py プロジェクト: sisoe24/PodcastTool
 def set_audio_intro(self):
     """Set the intro audio from the list in the catalog_names json file."""
     self.audio_intro = util.catalog_names()["intro"]
     LOGGER.debug("audio intro files: %s", self.audio_intro)
コード例 #9
0
class CatalogFrame(tk.Frame):
    """Catalog page of the gui."""
    _catalog_list = util.catalog_names()
    _updated_names = {"docenti": [], "corsi": []}

    def __init__(self, parent, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)

        _catalog_frame = ttk.Frame(self, width=420, height=800)
        _catalog_frame.grid(column=0, row=0, rowspan=2)

        self._options_frame = ttk.Frame(self, width=300, height=500)
        self._options_frame.grid(column=1, row=0, sticky=tk.N)
        self._options_frame.grid_propagate(False)

        self._tree_list = ttk.Treeview(_catalog_frame, height=24,
                                       columns=("names_short", "names_long"))
        self._tree_list.grid(column=0, row=0, columnspan=3, rowspan=3)
        self._generate_tree_columns()

        # load list frame
        _label_lista = ttk.LabelFrame(self._options_frame, text="Liste nomi")
        _label_lista.grid(column=3, row=0, sticky=tk.NW)

        self._selected_catalog = ttk.Combobox(_label_lista,
                                              value=["docenti", "corsi"],
                                              width=10, state="readonly")
        self._selected_catalog.grid(column=0, row=0, pady=10, sticky=tk.E)

        ttk.Button(_label_lista, text="Carica lista",
                   command=self._load_catalog).grid(column=1, row=0, padx=10)

        # insert new frame
        self._insert_frame = ttk.LabelFrame(self._options_frame,
                                            text="Aggiungi nuovo nome")
        self._insert_frame.grid(column=3, row=1, sticky=tk.N)

        ttk.Label(self._insert_frame, text="abbr.").grid(column=0, row=1,
                                                         sticky=tk.W)
        self._short_name = ttk.Entry(self._insert_frame)
        self._short_name.grid(column=1, row=1)

        ttk.Label(self._insert_frame, text="intero").grid(column=0, row=2,
                                                          sticky=tk.W)
        self._long_name = ttk.Entry(self._insert_frame)
        self._long_name.grid(column=1, row=2)

        self._course = None

        ttk.Label(self._insert_frame, text="lang").grid(column=0, row=4,
                                                        sticky=tk.W)
        self._lang_select = ttk.Combobox(self._insert_frame, state="readonly",
                                         value=["it", "en"], width=5)
        self._lang_select.grid(column=1, row=4, sticky=tk.W)
        self._lang_select.current(0)

        ttk.Button(self._insert_frame, text="Aggiungi",
                   command=self._insert_to_catalog).grid(column=1, row=4,
                                                         sticky=tk.E)

        self._btn_save = ttk.Button(self._options_frame,
                                    text="Salva modifiche", state="disabled",
                                    command=self._save_new_catalog)
        self._btn_save.grid(column=3, row=2, pady=15)

        ttk.Button(self._options_frame, text="Cancella nome selezionato",
                   command=self._delete_selected).grid(column=3, row=3)

    def _course_path(self):
        """Add course path to new courses."""
        value = ["ALP", "ELM", "EMP", "TTS"]
        if self._selected_catalog.get() == "corsi":

            ttk.Label(self._insert_frame, text="corso",
                      name="corse_l").grid(column=0, row=3)

            self._course = ttk.Combobox(self._insert_frame, value=value,
                                        state="readonly", width=5,
                                        name="corse_p")
            self._course.grid(column=1, row=3, sticky=tk.E)
            # self._course = course.get()

        if self._selected_catalog.get() == "docenti":
            for widget in self._insert_frame.winfo_children():
                if "corse" in widget.winfo_name():
                    widget.destroy()

    @property
    def _language(self):
        """Return the language selected: it or eng."""
        return self._lang_select.get()

    def _check_name_size(self, course_name):
        """Check if name course is 3 letters long otherwise raise error."""
        if self.get_catalog == "corsi" and not len(course_name) == 3:
            raise ValueError("Course name has to be 3 letters long")

    def _generate_tree_columns(self):
        """Generate columns for the treeview widget."""
        self._tree_list["show"] = "headings"
        self._tree_list.heading('names_short', text='Nome abbreviato')
        self._tree_list.column('names_short', width=150)
        self._tree_list.heading('names_long', text='Nome intero')
        self._tree_list.column('names_long', width=300)

        self._tree_list.tag_configure("oddrow", background='gray90')
        self._tree_list.tag_configure("evenrow", background='gray99')

    @property
    def get_catalog(self):
        """Return the catalog name selected from the combobox widget."""
        return self._selected_catalog.get()

    def _refresh_list(self):
        """Refresh (delete) list in treeview widget when loading other list."""
        self._tree_list.delete(*self._tree_list.get_children())

    def _reset_list(self):
        """When loading catalog, reset modification that have not be saved."""
        self._updated_names = {"docenti": [], "corsi": []}
        self._catalog_list = util.catalog_names()

    def _load_catalog(self):
        """Load name list into treeview widget."""
        self._reset_list()
        self._refresh_list()
        self._course_path()

        # self._btn_insert["state"] = "active"

        row_colors = ["oddrow", "evenrow"]
        catalog_names = sorted(self._catalog_list[self.get_catalog].items())
        for index, names in enumerate(catalog_names):
            if index % 2 == 0:
                self._tree_list.insert('', index, names[0],
                                       tags=(row_colors[index - index]))
            else:
                self._tree_list.insert('', index, names[0],
                                       tags=(row_colors[index - index + 1]))

            self._tree_list.set(names[0], 'names_short', names[0])
            try:
                self._tree_list.set(names[0], 'names_long',
                                    names[1]["course_name"])
            except TypeError:
                self._tree_list.set(names[0], 'names_long', names[1])

    def _delete_selected(self):
        """Delete selected element from treeview widget."""
        try:
            selected_item = self._tree_list.selection()[0]
        except IndexError:
            messagebox.showinfo(title="Cancella",
                                message="Nessun nome selezionato")
            return
        confirm = messagebox.askyesno(title="Cancella selezione",
                                      message=(f"Cancellare: {selected_item}?")
                                      )
        if confirm:
            self._tree_list.delete(selected_item)
            self._delete_from_catalog(selected_item)
            self._btn_save["state"] = "active"

    def _delete_from_catalog(self, delete_key):
        """Delete key from class catalog list."""
        # TODO: currently not deleting the file on disk?
        self._catalog_list[self.get_catalog].pop(delete_key)

    def _get_new_names(self):
        """Return a tuple with new names to insert taken from Entry widget.

        Return:
            tuple - short_name and long_name variables.
        """
        if not self._short_name.get() or not self._long_name.get():
            messagebox.showinfo(title="Errore", message="Nome invalido")
            return None

        _ = self._short_name.get().strip()

        # TODO: should do better checking of typos example:
        # if there are two spaces then it will insert 2 trailing
        if self.get_catalog == "docenti":
            short_name = _.replace(" ", "_").title()
        else:
            short_name = _.replace(" ", "_").upper()
        del _

        long_name = self._long_name.get().strip().title()
        return (short_name, long_name)

    def _insert_to_catalog(self):
        """Insert new name into treeview widget."""
        try:
            short_name, long_name = self._get_new_names()
            self._check_name_size(short_name)

        except TypeError:
            messagebox.showinfo(title="Errore",
                                message="Nessun nome inserito")

        except tk._tkinter.TclError:
            messagebox.showerror(title="Errore", message="Nome esiste già!")

        except ValueError:
            messagebox.showerror(
                title="nome corso",
                message="Nome del corso dovrebbe avere solo 3 lettere")
        else:
            if self.get_catalog == "docenti":
                self._catalog_list[self.get_catalog].update(
                    {short_name: long_name})

            else:
                course_path = self._course.get()
                if not course_path:
                    messagebox.showerror(message="manca codice corso")
                    return
                self._catalog_list[self.get_catalog].update(
                    {short_name: {"course_name": long_name,
                                  "course_path": course_path}})

            self._tree_list.insert("", 0, short_name)
            self._tree_list.set(short_name, 'names_short', short_name)
            self._tree_list.set(short_name, 'names_long', long_name)

            self._updated_names[self.get_catalog].append(
                [long_name, self._language])
            self._btn_save["state"] = "active"

    def _save_new_catalog(self):
        """Save new verison of catalog after delete or added new names."""
        modification = [_ for _ in self._updated_names.values() if _]
        if modification:
            with open(util.catalog_file(), "w") as json_file:
                json.dump(self._catalog_list, json_file, indent=True)
            self.update()
            self._update_audio_library()
            messagebox.showinfo(message="Modifiche salvate!")
        else:
            messagebox.showinfo(message="Nessuna modifica?")

    def _update_audio_library(self):
        """Update audio library with deleting or adding the modifications."""
        for _, new_names in self._updated_names.items():
            for index, new_name in enumerate(new_names, 20):
                name, lang = new_name
                msg = f"Generating audio for: \n[{name}]"
                ttk.Label(self._options_frame, text=msg).grid(
                    column=3, row=index)
                path = util.get_path("include/audio/new_audio")
                util.generate_audio(text=name, path=path, lang=lang)
コード例 #10
0
 def _reset_list(self):
     """When loading catalog, reset modification that have not be saved."""
     self._updated_names = {"docenti": [], "corsi": []}
     self._catalog_list = util.catalog_names()