python の練習2。 オーディプレイヤーに経過時間表示をつける

前回に引き続きpythonのオーディオプレイヤーの練習です。

時間をコントロールできるイベントとして、
プレイヤーに経過時間表示をつけてみたいと思います。

---

```py
elapsed_time = 0  # 秒数を記録
```

今回は１秒単位で記録することにしました。秒数を記録する変数をつくります。
そして、tkのラベルにセットします。
秒数から分と秒を得るのに、divmod()がワンライナーで書けるので素敵です。

    def update_time_label():    
        minutes, seconds = divmod(elapsed_time, 60)
        time_str = f"{minutes:02}:{seconds:02}"
        time_label.config(text=time_str)

１秒毎に時間更新＋描画更新する関数を作って
その関数を非同期実行するためにスレッドを作りました。

```py
from threading import Thread
import time

def count_time():
    self.elapsed_time = 0
    while pygame.mixer.music.get_busy():
        self.update_time_label()
        time.sleep(1)
        self.elapsed_time += 1

Thread(target=count_time, daemon=True).start()
```

オーディオを自動停止、あるいは手動で停止したときをどうやって検知しようか検討しましたが、
pygame.mixer.musicから、オーディオ再生状況を取得できるようなので、これを利用して一括でかくことにしました。

    pygame.mixer.music.get_busy()

状態変数を不要に作らないの大事だとおもいます。（KONAMI)

---

全体構成はつぎのようになりました。

```py
import pygame
import tkinter as tk
from tkinter import filedialog
from threading import Thread
import time

class AudioPlayer:
    TIME_INIT_STR = "--:--"

    def __init__(self, tk_root):
        self.tk_root = tk_root
        self.tk_root.title("Audio Player")

        self.tk_root.geometry("480x320")
        self.tk_root.resizable(False, False)
        
        self.init_pygame()
        self.create_widgets()

    def init_pygame(self):
        self.audio_file_path = ""
        pygame.mixer.init()

    def load_audio(self):
        self.audio_file_path = filedialog.askopenfilename(filetypes=[("Audio Files", "*.mp3")])
        if self.audio_file_path:
            self.stop_audio()

            pygame.mixer.music.load(self.audio_file_path)
            self.status_label.config(text=f"Loaded: {self.audio_file_path}")
            self.elapsed_time = 0
            self.update_time_label()

    def play_audio(self):
        if len(self.audio_file_path) > 0:
            pygame.mixer.music.play()
            audio_file_name = self.audio_file_path.split('/')[-1]
            self.status_label.config(text=f"Playing... {audio_file_name}")
            self.start_time_counter()

    def stop_audio(self):
        pygame.mixer.music.stop()
        self.elapsed_time = 0
        self.status_label.config(text="Stopped")
        self.time_label.config(text=AudioPlayer.TIME_INIT_STR)

    def start_time_counter(self):
        def count_time():
            self.elapsed_time = 0
            while pygame.mixer.music.get_busy():
                self.update_time_label()
                time.sleep(1)
                self.elapsed_time += 1
            self.time_label.config(text=AudioPlayer.TIME_INIT_STR)

        Thread(target=count_time, daemon=True).start()

    def update_time_label(self):
        minutes, seconds = divmod(self.elapsed_time, 60)
        time_str = f"{minutes:02}:{seconds:02}"
        self.time_label.config(text=time_str)

    def create_widgets(self):
        load_button = tk.Button(self.tk_root, text="Load", command=self.load_audio)
        play_button = tk.Button(self.tk_root, text="Play", command=self.play_audio)
        stop_button = tk.Button(self.tk_root, text="Stop", command=self.stop_audio)
        
        load_button.pack(pady=5)
        play_button.pack(pady=5)
        stop_button.pack(pady=5)
        
        self.status_label = tk.Label(self.tk_root, text="No file loaded")
        self.status_label.pack(pady=5)

        self.time_label = tk.Label(self.tk_root, text=AudioPlayer.TIME_INIT_STR, font=("Helvetica", 16))
        self.time_label.pack(pady=5)

if __name__ == '__main__':
    tk_tk_root = tk.Tk()
    app = AudioPlayer(tk_tk_root)
    tk_tk_root.mainloop()
```

実行結果

![Screenshot from 2024-07-07 12-41-18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812996/ee85f6a9-235c-14ec-c089-078b914a621e.png)


スクショじゃわかりませんが、時間表示できるようになりました！

オーディオが再生し終わったら下記の画面になりました。

![Screenshot from 2024-07-07 12-43-45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812996/2062c011-0b9c-45a1-b0c5-19266039cc35.png)