diff --git a/xiaomusic/config.py b/xiaomusic/config.py
index b38e126..e65a8d3 100644
--- a/xiaomusic/config.py
+++ b/xiaomusic/config.py
@@ -16,6 +16,7 @@ def default_key_word_dict():
"播放本地歌曲": "playlocal",
"关机": "stop",
"下一首": "play_next",
+ "上一首": "play_prev",
"单曲循环": "set_play_type_one",
"全部循环": "set_play_type_all",
"随机播放": "set_random_play",
@@ -46,6 +47,7 @@ def default_key_match_order():
"分钟后关机",
"播放歌曲",
"下一首",
+ "上一首",
"单曲循环",
"全部循环",
"随机播放",
diff --git a/xiaomusic/static/app.js b/xiaomusic/static/app.js
index 35e5a8d..981ece2 100644
--- a/xiaomusic/static/app.js
+++ b/xiaomusic/static/app.js
@@ -1,6 +1,9 @@
$(function(){
$container=$("#cmds");
+ append_op_button_name("加入收藏");
+ append_op_button_name("取消收藏");
+
const PLAY_TYPE_ONE = 0; // 单曲循环
const PLAY_TYPE_ALL = 1; // 全部循环
const PLAY_TYPE_RND = 2; // 随机播放
@@ -8,12 +11,11 @@ $(function(){
append_op_button("play_type_one", "单曲循环", "单曲循环");
append_op_button("play_type_rnd", "随机播放", "随机播放");
- append_op_button_name("刷新列表");
- append_op_button_name("下一首");
+ append_op_button_name("上一首");
append_op_button_name("关机");
+ append_op_button_name("下一首");
- append_op_button_name("加入收藏");
- append_op_button_name("取消收藏");
+ append_op_button_name("刷新列表");
$container.append($("
"));
@@ -100,8 +102,7 @@ $(function(){
const selectedValue = $(this).val();
localStorage.setItem('cur_playlist', selectedValue);
$('#music_name').empty();
- const sorted_musics = data[selectedValue].sort(custom_sort_key);
- $.each(sorted_musics, function(index, item) {
+ $.each(data[selectedValue], function(index, item) {
$('#music_name').append($('').val(item).text(item));
});
});
@@ -273,23 +274,4 @@ $(function(){
}
});
}
-
- function custom_sort_key(a, b) {
- // 使用正则表达式提取数字前缀
- const numericPrefixA = a.match(/^(\d+)/) ? parseInt(a.match(/^(\d+)/)[1], 10) : null;
- const numericPrefixB = b.match(/^(\d+)/) ? parseInt(b.match(/^(\d+)/)[1], 10) : null;
-
- // 如果两个键都有数字前缀,则按数字大小排序
- if (numericPrefixA !== null && numericPrefixB !== null) {
- return numericPrefixA - numericPrefixB;
- }
-
- // 如果一个键有数字前缀而另一个没有,则有数字前缀的键排在前面
- if (numericPrefixA !== null) return -1;
- if (numericPrefixB !== null) return 1;
-
- // 如果两个键都没有数字前缀,则按照常规字符串排序
- return a.localeCompare(b);
- }
-
});
diff --git a/xiaomusic/xiaomusic.py b/xiaomusic/xiaomusic.py
index ebc57e7..d5d5c31 100644
--- a/xiaomusic/xiaomusic.py
+++ b/xiaomusic/xiaomusic.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
import asyncio
+import copy
import json
import logging
import math
@@ -721,6 +722,9 @@ class XiaoMusic:
async def play_next(self, did="", **kwargs):
return await self.devices[did].play_next()
+ async def play_prev(self, did="", **kwargs):
+ return await self.devices[did].play_prev()
+
# 停止
async def stop(self, did="", arg1="", **kwargs):
return await self.devices[did].stop(arg1=arg1)
@@ -797,7 +801,7 @@ class XiaoMusic:
# 正在播放中的音乐
def playingmusic(self, did):
- cur_music = self.devices[did].cur_music
+ cur_music = self.devices[did].get_cur_music()
self.log.debug(f"playingmusic. cur_music:{cur_music}")
return cur_music
@@ -841,7 +845,6 @@ class XiaoMusic:
def save_cur_config(self):
for did in self.config.devices.keys():
deviceobj = self.devices.get(did)
- self.log.info(deviceobj.device)
if deviceobj is not None:
self.config.devices[did] = deviceobj.device
data = asdict(self.config)
@@ -917,7 +920,6 @@ class XiaoMusicDevice:
self.ffmpeg_location = self.config.ffmpeg_location
self._download_proc = None # 下载对象
- self.cur_music = self.device.cur_music
self._next_timer = None
self._timeout = 0
self._playing = False
@@ -926,12 +928,21 @@ class XiaoMusicDevice:
self._last_cmd = None
self.update_playlist()
+ def get_cur_music(self):
+ return self.device.cur_music
+
# 初始化播放列表
def update_playlist(self):
- self._cur_play_list = self.device.cur_playlist
- if self._cur_play_list not in self.xiaomusic.music_list:
- self._cur_play_list = "全部"
- self._play_list = self.xiaomusic.music_list.get(self._cur_play_list)
+ if self.device.cur_playlist not in self.xiaomusic.music_list:
+ self.device.cur_playlist = "全部"
+
+ list_name = self.device.cur_playlist
+ self._play_list = copy.copy(self.xiaomusic.music_list[list_name])
+ if self.device.play_type == PLAY_TYPE_RND:
+ random.shuffle(self._play_list)
+ self.log.info(f"随机打乱 {list_name} {self._play_list}")
+ else:
+ self.log.info(f"没打乱 {list_name} {self._play_list}")
# 播放歌曲
async def play(self, name="", search_key=""):
@@ -944,7 +955,7 @@ class XiaoMusicDevice:
await self._play_next()
return
else:
- name = self.cur_music
+ name = self.get_cur_music()
self.log.info(f"play. search_key:{search_key} name:{name}")
# 本地歌曲不存在时下载
@@ -966,7 +977,7 @@ class XiaoMusicDevice:
async def _play_next(self):
self.log.info("开始播放下一首")
- name = self.cur_music
+ name = self.get_cur_music()
if (
self.device.play_type == PLAY_TYPE_ALL
or self.device.play_type == PLAY_TYPE_RND
@@ -974,7 +985,27 @@ class XiaoMusicDevice:
or (name not in self._play_list)
):
name = self.get_next_music()
- self.log.info(f"_play_next. name:{name}, cur_music:{self.cur_music}")
+ self.log.info(f"_play_next. name:{name}, cur_music:{self.get_cur_music()}")
+ if name == "":
+ await self.do_tts("本地没有歌曲")
+ return
+ await self._play(name)
+
+ # 上一首
+ async def play_prev(self):
+ return await self._play_prev()
+
+ async def _play_prev(self):
+ self.log.info("开始播放上一首")
+ name = self.get_cur_music()
+ if (
+ self.device.play_type == PLAY_TYPE_ALL
+ or self.device.play_type == PLAY_TYPE_RND
+ or name == ""
+ or (name not in self._play_list)
+ ):
+ name = self.get_prev_music()
+ self.log.info(f"_play_prev. name:{name}, cur_music:{self.get_cur_music()}")
if name == "":
await self.do_tts("本地没有歌曲")
return
@@ -988,7 +1019,7 @@ class XiaoMusicDevice:
await self._play_next()
return
else:
- name = self.cur_music
+ name = self.get_cur_music()
self.log.info(f"playlocal. name:{name}")
@@ -1004,10 +1035,9 @@ class XiaoMusicDevice:
self.cancel_group_next_timer()
self._playing = True
- self.cur_music = name
self.device.cur_music = name
- self.log.info(f"cur_music {self.cur_music}")
+ self.log.info(f"cur_music {self.get_cur_music()}")
sec, url = await self.xiaomusic.get_music_sec_url(name)
await self.group_force_stop_xiaoai()
self.log.info(f"播放 {url}")
@@ -1041,7 +1071,7 @@ class XiaoMusicDevice:
# 最大等8秒
sec = min(8, int(len(value) / 3))
await asyncio.sleep(sec)
- self.log.info(f"do_tts ok. cur_music:{self.cur_music}")
+ self.log.info(f"do_tts ok. cur_music:{self.get_cur_music()}")
await self.check_replay()
async def force_stop_xiaoai(self, device_id):
@@ -1143,51 +1173,62 @@ class XiaoMusicDevice:
self.log.info(f"add_download_music add_music {name}")
self.log.debug(self._play_list)
- # 获取下一首
- def get_next_music(self):
+ def get_music(self, direction="next"):
play_list_len = len(self._play_list)
if play_list_len == 0:
self.log.warning("当前播放列表没有歌曲")
return ""
index = 0
try:
- index = self._play_list.index(self.cur_music)
+ index = self._play_list.index(self.get_cur_music())
except ValueError:
pass
+
if play_list_len == 1:
- next_index = index # 当只有一首歌曲时保持当前索引不变
+ new_index = index # 当只有一首歌曲时保持当前索引不变
else:
- # 顺序往后找1个
- next_index = index + 1
- if next_index >= play_list_len:
- next_index = 0
- # 排除当前歌曲随机找1个
- if self.device.play_type == PLAY_TYPE_RND:
- indices = list(range(play_list_len))
- indices.remove(index)
- next_index = random.choice(indices)
- name = self._play_list[next_index]
+ if direction == "next":
+ new_index = index + 1
+ if new_index >= play_list_len:
+ new_index = 0
+ elif direction == "prev":
+ new_index = index - 1
+ if new_index < 0:
+ new_index = play_list_len - 1
+ else:
+ self.log.error("无效的方向参数")
+ return ""
+
+ name = self._play_list[new_index]
if not self.xiaomusic.is_music_exist(name):
- self._play_list.pop(next_index)
- self.log.info(f"pop not exist music:{name}")
- return self.get_next_music()
+ self._play_list.pop(new_index)
+ self.log.info(f"pop not exist music: {name}")
+ return self.get_music(direction)
return name
+ # 获取下一首
+ def get_next_music(self):
+ return self.get_music(direction="next")
+
+ # 获取上一首
+ def get_prev_music(self):
+ return self.get_music(direction="prev")
+
# 判断是否播放下一首歌曲
def check_play_next(self):
# 当前歌曲不在当前播放列表
- if self.cur_music not in self._play_list:
- self.log.info(f"当前歌曲 {self.cur_music} 不在当前播放列表")
+ if self.get_cur_music() not in self._play_list:
+ self.log.info(f"当前歌曲 {self.get_cur_music()} 不在当前播放列表")
return True
# 当前没我在播放的歌曲
- if self.cur_music == "":
+ if self.get_cur_music() == "":
self.log.info("当前没我在播放的歌曲")
return True
else:
# 当前播放的歌曲不存在了
- if not self.xiaomusic.is_music_exist(self.cur_music):
- self.log.info(f"当前播放的歌曲 {self.cur_music} 不存在了")
+ if not self.xiaomusic.is_music_exist(self.get_cur_music()):
+ self.log.info(f"当前播放的歌曲 {self.get_cur_music()} 不存在了")
return True
return False
@@ -1289,12 +1330,12 @@ class XiaoMusicDevice:
self.xiaomusic.save_cur_config()
tts = PLAY_TYPE_TTS[play_type]
await self.do_tts(tts)
+ self.update_playlist()
async def play_music_list(self, list_name, music_name):
self._last_cmd = "play_music_list"
- self._cur_play_list = list_name
self.device.cur_playlist = list_name
- self._play_list = self.xiaomusic.music_list[list_name]
+ self.update_playlist()
self.log.info(f"开始播放列表{list_name}")
await self._play(music_name)
@@ -1344,7 +1385,7 @@ class XiaoMusicDevice:
device.cancel_next_timer()
def get_cur_play_list(self):
- return self._cur_play_list
+ return self.device.cur_playlist
# 清空所有定时器
def cancel_all_timer(self):