📄 showlyricdlg.c
字号:
/* * * Author: Allan <qimingos_lsk@163.com>, (C) 2005-2007 * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */#include "../include/ShowLyric.h"#include "../include/EditLyricDlg.h"#include "../include/ShowLyricDlg.h"#define EDIT_LYRIC_GLADE_FILE "/usr/share/ShowLyric/EditLyricDlg.glade"#define this theApp.m_LyricWndvoid LyricWndInit(){ this.ShowLyric = ShowLyric; this.ParseLyric = ParseLyric; this.SmartShowWnd = SmartShowWnd; this.ClearLyric = ClearLyric; this.RefreshLyricSetting = RefreshLyricSetting; this.m_TimerId = 0; this._m_current = NULL; this.m_ListCurrLyric = NULL; this.m_bScrollMouseChange = FALSE; this.m_bLyricChanged = FALSE; this.m_bLyricChanging = FALSE; GtkWidget* pShowLyric = glade_xml_get_widget(theApp.m_xml, "ShowLyric"); gtk_window_set_keep_above(GTK_WINDOW(pShowLyric), TRUE); glade_xml_signal_connect_data(theApp.m_xml, "on_ShowLyric_window_state_event", G_CALLBACK(on_ShowLyric_window_state_event), pShowLyric); glade_xml_signal_connect_data(theApp.m_xml, "on_ShowLyric_delete_event", G_CALLBACK(on_ShowLyric_delete_event), pShowLyric); glade_xml_signal_connect_data(theApp.m_xml, "on_ShowLyric_button_press_event", G_CALLBACK(on_ShowLyric_button_press_event), pShowLyric); glade_xml_signal_connect_data(theApp.m_xml, "on_ShowLyric_scroll_event", G_CALLBACK(on_ShowLyric_scroll_event), pShowLyric); glade_xml_signal_connect_data(theApp.m_xml, "on_ShowLyric_motion_notify_event", G_CALLBACK(on_ShowLyric_motion_notify_event), pShowLyric); glade_xml_signal_connect_data(theApp.m_xml, "on_MenuEditLyric_activate", G_CALLBACK(on_MenuEditLyric_activate), pShowLyric); glade_xml_signal_connect_data(theApp.m_xml, "on_MenuReDownLoad_activate", G_CALLBACK(on_MenuReDownLoad_activate), pShowLyric); glade_xml_signal_connect_data(theApp.m_xml, "on_MenuConfig_activate", G_CALLBACK(on_MenuConfig_activate), pShowLyric); glade_xml_signal_connect_data(theApp.m_xml, "on_MenuAbout_activate", G_CALLBACK(on_MenuAbout_activate), pShowLyric); glade_xml_signal_connect_data(theApp.m_xml, "on_MenuUpTime_activate", G_CALLBACK(on_MenuUpTime_activate), pShowLyric); glade_xml_signal_connect_data(theApp.m_xml, "on_MenuDownTime_activate", G_CALLBACK(on_MenuDownTime_activate), pShowLyric); glade_xml_signal_connect_data(theApp.m_xml, "on_MenuMouseScroll_toggled", G_CALLBACK(on_MenuMouseScroll_toggled), pShowLyric); glade_xml_signal_connect_data(theApp.m_xml, "on_MenuShowBroad_toggled", G_CALLBACK(on_MenuShowBroad_toggled), pShowLyric); this.m_EditLyricDlg.m_pEditLyricXML = glade_xml_new(EDIT_LYRIC_GLADE_FILE, NULL, NULL); EditLyricDlgInit(); SmartShowWnd(FALSE);}// 将字符串“00:12.123”转化为数字int _GetTime(gchar* lpszTime){ int iMS = 0, iSec = 0, iMinute = 0; gchar* lpszTmp= NULL; int iBegin = StrLeftFind(lpszTime, 0, '.'); if (iBegin >= 0) { lpszTmp = lpszTime + iBegin; *lpszTmp = 0; lpszTmp++; iMS = atoi(lpszTmp); } iBegin = StrLeftFind(lpszTime, 0, ':'); if (iBegin >= 0) { lpszTmp = lpszTime + iBegin; *lpszTmp = 0; lpszTmp++; iSec = atoi(lpszTmp); } iMinute = atoi(lpszTime); return (iMinute * 60 + iSec) * 1000 + iMS;}void _ClearList(){ g_assert(!this.m_bLyricChanging); // TODO: 保存修改后的歌词 GList *list= this.m_ListCurrLyric; GList* OldList = list; this.m_ListCurrLyric = NULL; this._m_current = NULL; if (OldList) { gtk_timeout_remove(this.m_TimerId); usleep(500); } GtkWidget* pVbox = glade_xml_get_widget(theApp.m_xml, "vboxLyrics"); while (list) { LyricItem *item = (LyricItem *) list->data; g_free(item->lpszValue); gtk_widget_destroy(item->pLabel); g_free(item); list = g_list_next(list); } g_list_free(OldList); gtk_widget_hide(GTK_WIDGET(pVbox));}// 将一个时间点的歌词加入到链表里面去void _ParseLine(int iTime, gchar* lpszValue){ GList* list = g_list_first(this.m_ListCurrLyric); LyricItem *pNewItem = (LyricItem *)g_malloc0(sizeof(LyricItem)); pNewItem->iTime = iTime; pNewItem->lpszValue = (gchar *)g_malloc0(strlen(lpszValue) + 1); strcpy(pNewItem->lpszValue, lpszValue); gchar* pWork = pNewItem->lpszValue; while (*pWork != 0) { if (*pWork == '\r' || *pWork == '\n') *pWork = '\0'; pWork++; } while (list) { LyricItem* lpItem = list->data; if (lpItem->iTime > iTime) { this.m_ListCurrLyric = g_list_insert_before(this.m_ListCurrLyric, list, pNewItem); return; } list = g_list_next(list); } this.m_ListCurrLyric = g_list_append(this.m_ListCurrLyric, pNewItem);}// 解析歌词gboolean ParseLyric(gchar* lpszLyricFileName){ _ClearList(); FILE * pLyricFile = fopen(lpszLyricFileName, "r"); if (!pLyricFile) { LyricLog("加载歌词文件%s失败", lpszLyricFileName); theApp.m_LyricWnd.SmartShowWnd(FALSE); return FALSE; } gchar szBuf[512] = { 0 }; fgets(szBuf, 512, pLyricFile); fseek(pLyricFile, 0, SEEK_END); int iLen = ftell(pLyricFile); fseek(pLyricFile, 0, SEEK_SET); gchar * lpszLine = (gchar *)g_malloc(iLen); while (fgets(lpszLine, iLen, pLyricFile) != NULL) { int iEnd = StrLeftFind(lpszLine, 0, ']'); if (iEnd > 0) { gchar* pValue = lpszLine + iEnd; *pValue = 0; pValue++; gchar* lpszTimes = lpszLine; int iBegin = StrLeftFind(lpszTimes, 0, '['); while (iBegin >= 0) { gchar* lpszTime = lpszTimes + iBegin; *lpszTime = 0; lpszTime++; if (lpszTime[strlen(lpszTime) - 1] == ']') lpszTime[strlen(lpszTime) - 1] = 0; // 转换时间pTime为iTime int iTime = _GetTime(lpszTime); _ParseLine(iTime, pValue); iBegin = StrLeftFind(lpszTimes, 0, '['); } } } fclose(pLyricFile); pLyricFile = NULL; g_free(lpszLine); lpszLine = NULL; if (g_list_length(this.m_ListCurrLyric) > 0) { theApp.SetAppState(AS_ShowingLyric); ShowLyric(); } return TRUE;}void ClearLyric(){ LyricDebug("ClearLyric------------------------------------"); this.m_bLyricChanging = FALSE; this.m_bLyricChanged = FALSE; _ClearList();}void SmartShowWnd(gboolean bShow){ GtkWidget * pEditLyricDlg = glade_xml_get_widget( this.m_EditLyricDlg.m_pEditLyricXML, "EditLyricDlg"); GtkWidget *pLyricWnd = glade_xml_get_widget(theApp.m_xml, "ShowLyric"); if (this.m_EditLyricDlg.m_bEditing) { gtk_widget_show(pEditLyricDlg); gtk_widget_hide(pLyricWnd); return; } else { gtk_widget_hide(pEditLyricDlg); } if (!theApp.m_configs.bSmartShowWin) return; if (bShow) { gtk_window_set_keep_above(GTK_WINDOW(pLyricWnd), TRUE); gtk_window_move(GTK_WINDOW(pLyricWnd), theApp.m_configs.pos.iX, theApp.m_configs.pos.iY); gtk_widget_show(pLyricWnd); } else { gtk_widget_hide(pLyricWnd); }}gboolean ScrollLyric(gpointer data){ if (this.m_bLyricChanging) return TRUE; GtkWidget *pLyricWnd = glade_xml_get_widget(theApp.m_xml, "ShowLyric"); GtkWidget* pVbox = glade_xml_get_widget(theApp.m_xml, "vboxLyrics"); GtkWidget* pLayout = glade_xml_get_widget(theApp.m_xml, "layoutLyrics"); int iTime = theApp.m_player.GetCurrTime(); GList *list= this.m_ListCurrLyric; GList *previous= this._m_current; GList *current= this._m_current; //int the_y = GTK_WIDGET(pLyricWnd)->allocation.height / 2; if (!current && list) { current = list; } else if (!current && !list) { return TRUE; } int iCCC = 0; // 找到当前项 // 往后找,直到使当前项的时间大于给出的时间为止 while (TRUE) { if (iCCC++ > 1000) { break; } if (((LyricItem *) current->data)->iTime > iTime) { break; } else { if (current->next) // 如果不是最后一个 current = current->next; else { break; } } } if (!current || !current->data) { LyricLog("current is empty!"); return TRUE; } // 如果当前项已经变更则更新 if (previous != current) this._m_current = current; // set colors int threshold = 300; GList *p= NULL; iCCC = 0; for (p = list; p; p = p->next) { if (iCCC++ > 1000) { break; } gint p_time = ((LyricItem *) (p->data))->iTime; gint pn_time = p->next ? ((LyricItem *) (p->next->data))->iTime : 0; if (iTime < p_time - threshold || (p->next && pn_time + threshold < iTime)) { if (((LyricItem *) p->data)->process_color) { ((LyricItem *) p->data)->process_color = FALSE; gtk_widget_modify_fg(((LyricItem *) p->data)->pLabel, GTK_STATE_NORMAL, &theApp.m_configs.colors.normal); } } else if (iTime < p_time + threshold) { int delta = (iTime - p_time + threshold) / 2; GdkColor color; color_between(&theApp.m_configs.colors.normal, &theApp.m_configs.colors.current, (gdouble) delta / threshold, &color); gtk_widget_modify_fg(((LyricItem *) p->data)->pLabel, GTK_STATE_NORMAL, &color); ((LyricItem *) p->data)->process_color = TRUE; } else if (p->next && iTime < pn_time - threshold) { gtk_widget_modify_fg(((LyricItem *) p->data)->pLabel, GTK_STATE_NORMAL, &theApp.m_configs.colors.current); ((LyricItem *) p->data)->process_color = TRUE; } else if (p->next && iTime < pn_time + threshold) { int delta = (pn_time + threshold - iTime) / 2; GdkColor color; color_between(&theApp.m_configs.colors.normal, &theApp.m_configs.colors.current, (gdouble) delta / threshold, &color); gtk_widget_modify_fg(((LyricItem *) p->data)->pLabel, GTK_STATE_NORMAL, &color); ((LyricItem *) p->data)->process_color = TRUE; } } // 如果已经是最后一项了,直接返回 if (!current->next || !current->data) { return TRUE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -