回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

M10音乐播放器 简单

头像 rzyzzxw 2025.07.21 14 0

7.21

 

【写在前面】

想搞一个小智AI通过MCP播放M10上的本地音乐,搞来搞去没有成,先做了一个M10版的音乐播放器,用来听听音乐。

647a64698571730099a76ab0ef7d9d32.jpg

 

材料清单

  • M10行空板 X1
  • M10电池扩展板组合 X1
  • 蓝牙小音箱 X

步骤1 把蓝牙小音箱连接行空板M10

参考文章:

行空板M10连接蓝牙音箱详细教程- Makelog(造物记)

步骤2 代码准备

从B站网友的开源项目中拿到了一段代码,想改写成小智MCP控制M10本地播放mp3的播放器,没有成功。

先是改写成了通过终端输入命令来控制M10播放音乐的功能。

image.png
image.png

 

代码如下,贴在这里存档。

注:本代码需在mind+中运行,命令从终端输入。

代码
# local_player.py
import os
import pygame
import threading
import time
import random

class MusicPlayer:
    def __init__(self):
        self.current_play_list = []
        self.current_play_mode = "single"
        self.current_song_index = -1
        self.is_playing = False
        self.is_paused = False
        
        pygame.mixer.init()
        print("音频系统初始化完成")
        
        # 启动播放线程
        self.playback_thread = threading.Thread(target=self._playback_thread, daemon=True)
        self.playback_thread.start()
    
    def _playback_thread(self):
        while True:
            if self.is_playing and not self.is_paused:
                if not pygame.mixer.music.get_busy():
                    self._play_next()
                time.sleep(0.1)
            else:
                time.sleep(0.5)
    
    def _play_next(self):
        if not self.current_play_list:
            return
        
        if self.current_play_mode == "single":
            # 单曲循环,重新播放当前歌曲
            pass
        elif self.current_play_mode == "list":
            self.current_song_index = (self.current_song_index + 1) % len(self.current_play_list)
        elif self.current_play_mode == "random":
            self.current_song_index = random.randint(0, len(self.current_play_list) - 1)
        
        self._play_current()
    
    def _play_current(self):
        if not self.current_play_list or self.current_song_index < 0:
            return
        
        song_file = self.current_play_list[self.current_song_index]
        song_path = os.path.join("music_file", song_file)
        
        if os.path.exists(song_path):
            try:
                pygame.mixer.music.load(song_path)
                pygame.mixer.music.play()
                print(f"正在播放: {song_file}")
            except:
                print(f"播放失败: {song_file}")
    
    def play(self, song_name="", play_mode="single"):
        # 获取音乐文件列表
        music_files = [f for f in os.listdir("music_file") if f.endswith(".mp3")]
        
        if not music_files:
            print("没有可播放的音乐文件")
            return
        
        # 筛选歌曲
        if song_name:
            self.current_play_list = [f for f in music_files if song_name.lower() in f.lower()]
        else:
            self.current_play_list = music_files
        
        if not self.current_play_list:
            print(f"未找到匹配 '{song_name}' 的歌曲")
            return
        
        self.current_play_mode = play_mode
        self.current_song_index = 0 if play_mode != "random" else random.randint(0, len(self.current_play_list) - 1)
        self.is_playing = True
        self.is_paused = False
        self._play_current()
    
    def pause(self):
        if self.is_playing and not self.is_paused:
            pygame.mixer.music.pause()
            self.is_paused = True
            print("音乐已暂停")
    
    def unpause(self):
        if self.is_playing and self.is_paused:
            pygame.mixer.music.unpause()
            self.is_paused = False
            print("音乐已恢复")
    
    def stop(self):
        pygame.mixer.music.stop()
        self.is_playing = False
        self.is_paused = False
        print("音乐已停止")
    
    def next(self):
        if not self.current_play_list:
            print("播放列表为空")
            return
        
        self.current_play_mode = "list"  # 切换到列表模式
        self.current_song_index = (self.current_song_index + 1) % len(self.current_play_list)
        self._play_current()
    
    def previous(self):
        if not self.current_play_list:
            print("播放列表为空")
            return
        
        self.current_play_mode = "list"  # 切换到列表模式
        self.current_song_index = (self.current_song_index - 1) % len(self.current_play_list)
        self._play_current()

if __name__ == "__main__":
    player = MusicPlayer()
    
    # 示例用法
    player.play(play_mode="list")
    
    # 保持主线程运行
    try:
        while True:
            command = input("输入命令 (play/pause/stop/next/prev/exit): ").strip().lower()
            if command == "exit":
                break
            elif command == "play":
                player.play(play_mode="list")
            elif command == "pause":
                player.pause()
            elif command == "stop":
                player.stop()
            elif command == "next":
                player.next()
            elif command == "prev":
                player.previous()
    except KeyboardInterrupt:
        print("\n程序退出")

步骤3 改写代码成屏幕触摸按钮控制方式

用终端命令控制,太不友好了,继续改写成按钮控制播放,并且增加音量控制按钮。

8e2162072c19eede54e959dbd4f38b4.png

代码如下:

代码
# local_player.py
import os
import pygame
import threading
import time
import random
import sys
from unihiker import GUI

# 添加扩展库路径
sys.path.append("/root/mindplus/.lib/thirdExtension/nick-unihiker_sound-thirdex")
from unihiker_sound import SoundManager

# 创建播放器实例
player = None
status_label = None
volume_label = None
unihiker_sound = None
current_volume = 60  # 默认音量

# 事件回调函数
def button_click1():
    player.play(play_mode="list")
    update_status("播放中")

def button_click2():
    player.pause()
    update_status("已暂停")

def button_click3():
    player.unpause()
    update_status("播放中")

def button_click4():
    player.stop()
    update_status("已停止")

def button_click5():
    player.next()
    update_status("下一首")

def button_click6():
    player.previous()
    update_status("上一首")

def button_click_vol_up():
    global current_volume
    current_volume = min(100, current_volume + 10)
    unihiker_sound.set_volume(current_volume)
    update_volume_display()
    update_status(f"音量 + → {current_volume}")

def button_click_vol_down():
    global current_volume
    current_volume = max(0, current_volume - 10)
    unihiker_sound.set_volume(current_volume)
    update_volume_display()
    update_status(f"音量 - → {current_volume}")

def update_status(text):
    """更新状态显示"""
    global status_label
    if status_label:
        status_label.config(text=f"状态: {text}")
    else:
        print(f"状态: {text}")

def update_volume_display():
    """更新音量显示"""
    global volume_label
    if volume_label:
        volume_label.config(text=f"音量: {current_volume}%")
    else:
        print(f"音量: {current_volume}%")

# 初始化GUI
u_gui = GUI()
u_gui.draw_image(image="back.png", x=0, y=0)
u_gui.draw_text(text="M10音乐播放器", x=10, y=0, font_size=20, color="#FFFFFF")

# 添加状态显示标签
status_label = u_gui.draw_text(text="状态: 就绪", x=150, y=20, font_size=12, color="#FFFFFF")

# 添加音量显示标签
volume_label = u_gui.draw_text(text=f"音量: {current_volume}%", x=150, y=40, font_size=12, color="#FFFFFF")

# 创建播放控制按钮
play_btn = u_gui.add_button(text="播放", x=30, y=40, w=60, h=30, onclick=button_click1)
pause_btn = u_gui.add_button(text="暂停", x=30, y=80, w=60, h=30, onclick=button_click2)
resume_btn = u_gui.add_button(text="继续", x=30, y=120, w=60, h=30, onclick=button_click3)
stop_btn = u_gui.add_button(text="停止", x=30, y=160, w=60, h=30, onclick=button_click4)
next_btn = u_gui.add_button(text="下一首", x=30, y=200, w=60, h=30, onclick=button_click5)
prev_btn = u_gui.add_button(text="上一首", x=30, y=240, w=60, h=30, onclick=button_click6)

# 创建音量控制按钮
vol_up_btn = u_gui.add_button(text="音量+", x=100, y=40, w=60, h=30, onclick=button_click_vol_up)
vol_down_btn = u_gui.add_button(text="音量-", x=100, y=80, w=60, h=30, onclick=button_click_vol_down)

class MusicPlayer:
    def __init__(self):
        self.current_play_list = []
        self.current_play_mode = "single"
        self.current_song_index = -1
        self.is_playing = False
        self.is_paused = False
        
        pygame.mixer.init()
        print("音频系统初始化完成")
        
        # 启动播放线程
        self.playback_thread = threading.Thread(target=self._playback_thread, daemon=True)
        self.playback_thread.start()
    
    def _playback_thread(self):
        while True:
            if self.is_playing and not self.is_paused:
                if not pygame.mixer.music.get_busy():
                    self._play_next()
                time.sleep(0.1)
            else:
                time.sleep(0.5)
    
    def _play_next(self):
        if not self.current_play_list:
            return
        
        if self.current_play_mode == "single":
            # 单曲循环,重新播放当前歌曲
            pass
        elif self.current_play_mode == "list":
            self.current_song_index = (self.current_song_index + 1) % len(self.current_play_list)
        elif self.current_play_mode == "random":
            self.current_song_index = random.randint(0, len(self.current_play_list) - 1)
        
        self._play_current()
    
    def _play_current(self):
        if not self.current_play_list or self.current_song_index < 0:
            return
        
        song_file = self.current_play_list[self.current_song_index]
        song_path = os.path.join("music_file", song_file)
        
        if os.path.exists(song_path):
            try:
                pygame.mixer.music.load(song_path)
                pygame.mixer.music.play()
                print(f"正在播放: {song_file}")
                update_status(f"播放中: {song_file}")
            except Exception as e:
                print(f"播放失败: {song_file}, 错误: {str(e)}")
                update_status(f"播放失败: {song_file}")
    
    def play(self, song_name="", play_mode="single"):
        # 如果已经在播放,先停止
        if self.is_playing:
            self.stop()
        
        # 获取音乐文件列表
        music_files = [f for f in os.listdir("music_file") if f.endswith(".mp3")]
        
        if not music_files:
            print("没有可播放的音乐文件")
            update_status("无音乐文件")
            return
        
        # 筛选歌曲
        if song_name:
            self.current_play_list = [f for f in music_files if song_name.lower() in f.lower()]
        else:
            self.current_play_list = music_files
        
        if not self.current_play_list:
            print(f"未找到匹配 '{song_name}' 的歌曲")
            update_status("未找到歌曲")
            return
        
        self.current_play_mode = play_mode
        self.current_song_index = 0 if play_mode != "random" else random.randint(0, len(self.current_play_list) - 1)
        self.is_playing = True
        self.is_paused = False
        self._play_current()
    
    def pause(self):
        if self.is_playing and not self.is_paused:
            pygame.mixer.music.pause()
            self.is_paused = True
            print("音乐已暂停")
            update_status("已暂停")
    
    def unpause(self):
        if self.is_playing and self.is_paused:
            pygame.mixer.music.unpause()
            self.is_paused = False
            print("音乐已恢复")
            update_status("播放中")
    
    def stop(self):
        if self.is_playing:
            pygame.mixer.music.stop()
            self.is_playing = False
            self.is_paused = False
            print("音乐已停止")
            update_status("已停止")
    
    def next(self):
        if not self.current_play_list:
            print("播放列表为空")
            return
        
        # 如果未在播放,先开始播放
        if not self.is_playing:
            self.play(play_mode="list")
            return
        
        self.current_play_mode = "list"  # 切换到列表模式
        self.current_song_index = (self.current_song_index + 1) % len(self.current_play_list)
        self._play_current()
        update_status("下一首")
    
    def previous(self):
        if not self.current_play_list:
            print("播放列表为空")
            return
        
        # 如果未在播放,先开始播放
        if not self.is_playing:
            self.play(play_mode="list")
            return
        
        self.current_play_mode = "list"  # 切换到列表模式
        self.current_song_index = (self.current_song_index - 1) % len(self.current_play_list)
        self._play_current()
        update_status("上一首")

if __name__ == "__main__":
    # 初始化声音管理器
    unihiker_sound = SoundManager()
    unihiker_sound.set_volume(current_volume)
    
    player = MusicPlayer()
    update_status("就绪")
    update_volume_display()
    
    # 保持程序运行
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("\n程序退出")

运行代码,可以用屏幕触摸按钮控制各种功能。

566b6953280242cb23fc09658207df5.png

注:这个代码上传后可以从M10启动运行。

使用说明:

确保音乐文件放在music_file目录中(MP3格式)

背景图片back.png需要存在(或修改为其他图片路径)

按钮功能:

播放:开始播放音乐(随机选择模式)

暂停:暂停当前播放

继续:从暂停处继续播放

停止:完全停止播放

下一首:切换到下一首歌曲

上一首:切换到上一首歌曲

音量+:增加10%音量(最大100%)

音量-:减少10%音量(最小0%)

当前音量百分比会实时显示在界面上

这个实现完全通过按钮控制音乐播放,无需终端输入命令,界面更加友好。

状态显示让用户随时了解当前播放状态。

本项目代码由DeepSeek协助完成,致谢。

评论

user-avatar