Skip to content

Commit

Permalink
修正播放列表中的“修复错误的文件路径”功能在媒体库更新后还需要重启软件才能生效的问题 #761
Browse files Browse the repository at this point in the history
  • Loading branch information
zhongyang219 committed Aug 18, 2024
1 parent f02766e commit bce59da
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 10 deletions.
24 changes: 15 additions & 9 deletions MusicPlayer2/SongDataManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,8 @@ void CSongDataManager::LoadSongData(std::wstring path)
ar >> song_info.total_discs;
}
m_song_data[song_info] = song_info; // 将读取到的一首歌曲信息添加到映射容器中

std::wstring file_name{ song_info.GetFileName() };
m_song_file_name_map[file_name].push_back(song_info.file_path);

UpdateFileNameMap(song_info);
}
}
catch (CArchiveException* exception)
Expand Down Expand Up @@ -402,6 +401,7 @@ void CSongDataManager::AddItem(const SongInfo& song)
ASSERT(!song.file_path.empty());
m_song_data[song] = song;
m_song_data_modified = true;
UpdateFileNameMap(song);
}

bool CSongDataManager::RemoveItem(const SongKey& key)
Expand Down Expand Up @@ -471,6 +471,12 @@ void CSongDataManager::ChangeFilePath(const wstring& file_path, const wstring& n
}
}

void CSongDataManager::UpdateFileNameMap(const SongInfo& song)
{
std::wstring file_name{ song.GetFileName() };
m_song_file_name_map[file_name].insert(song.file_path);
}

//计算两个字符串右侧匹配的字符数量
static int CalcualteStringRightMatchedCharNum(const std::wstring& str1, const std::wstring& str2)
{
Expand All @@ -496,23 +502,23 @@ bool CSongDataManager::FixWrongFilePath(wstring& file_path) const
{
if (iter->second.size() == 1) //媒体库中同名的文件只有一个时,直接修改为该文件的路径
{
file_path = iter->second.front();
file_path = *iter->second.begin();
fixed = true;
}
else if (iter->second.size() > 1) //媒体库中同名的文件有多个时,查找两个路径末尾相同字符数量最多的那项
{
size_t best_match_index{};
std::wstring best_match_path;
int max_matched_char_mun{};
for (size_t i{}; i < iter->second.size(); i++)
for (const auto& path : iter->second)
{
int cur_matched_char_num = CalcualteStringRightMatchedCharNum(file_path, iter->second[i]);
int cur_matched_char_num = CalcualteStringRightMatchedCharNum(file_path, path);
if (cur_matched_char_num > max_matched_char_mun)
{
max_matched_char_mun = cur_matched_char_num;
best_match_index = i;
best_match_path = path;
}
}
file_path = iter->second[best_match_index];
file_path = best_match_path;
fixed = true;
}
}
Expand Down
5 changes: 4 additions & 1 deletion MusicPlayer2/SongDataManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ class CSongDataManager
// 创建旧媒体库条目的新路径副本(不能用于cue文件)
void ChangeFilePath(const wstring& file_path, const wstring& new_path);

//将一个曲目信息更新到m_song_file_name_map中
void UpdateFileNameMap(const SongInfo& song);

//如果file_path不存在,则从媒体库中查找文件名相同的最佳匹配的项目,并将file_path更改为正确的路径
bool FixWrongFilePath(wstring& file_path) const;

Expand All @@ -63,5 +66,5 @@ class CSongDataManager
CString m_data_version;
// 用于保证m_song_data读写的线程安全,遍历/查找加读锁,添加/删除加写锁
mutable std::shared_mutex m_shared_mutex; // 线程同步对象
std::unordered_map<std::wstring, std::vector<std::wstring>> m_song_file_name_map; //保存文件名与SongInfo对象的对应关系
std::unordered_map<std::wstring, std::set<std::wstring>> m_song_file_name_map; //保存文件名与文件路径的对应关系(用于播放列表“修复错误的文件路径”功能)
};

2 comments on commit bce59da

@lrisora
Copy link
Contributor

@lrisora lrisora commented on bce59da Aug 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

使用FixWrongFilePath时需要加m_shared_mutex读锁
因为m_song_file_name_map读取时AddItem仍然会被反复调用
m_song_file_name_map的写入就依赖AddItem加的写锁就好
(可能不需要UpdateFileNameMap这层,直接让CSongDataManager以同等水平维护m_song_data和m_song_file_name_map即可)

不过FixWrongFilePath逻辑上仍有问题,m_song_file_name_map会同时拥有有效与无效的路径,
这使得匹配会优先使用原名即使其不存在
之前这个功能也依赖于”启动时移除不存在的文件“

确认文件是否存在很花时间,准确的说是所有文件api(如果量很大的话)
这导致一点问题,FixWrongFilePath可能需要阻塞AddItem相当一段时间,程序可能会卡一会(问题不大)

另外这个功能我觉得设计上有问题,如果文件命名随意那么极有可能匹配到错误的音频
比如如果有文件夹组织结构如下 /music/<album>/<track>.flac
之后删除了某个专辑,那么播放列表的项目就会被修复随意选择另一个专辑
对cue项目就更有问题,毕竟CDImage.xxx有那么多

不是反对这个功能,主要是UX有问题,这个功能最有可能被完全不理解它有什么用的人使用

@zhongyang219
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lrisora 确实有些问题,我后来想想觉得没有必要让CSongDataManager维护一个m_song_file_name_map,于是我现在改成了m_song_file_name_map实时构建,并将它从CSongDataManager中删除了,实时构建并不会花太多时间。
现在会忽略cue项目,并修正了会匹配到不存在的文件的问题。

Please sign in to comment.