Add lyrics parser

This commit is contained in:
daleclack 2023-09-23 22:05:14 +08:00
parent 789b6fca64
commit b3ac77c4e7
7 changed files with 162 additions and 14 deletions

View File

@ -61,7 +61,7 @@ if(WIN32)
set_property(SOURCE ../icon.rc APPEND PROPERTY set_property(SOURCE ../icon.rc APPEND PROPERTY
OBJECT_DEPENDS ${PROJECT_SOURCE_DIR}/../icon.ico OBJECT_DEPENDS ${PROJECT_SOURCE_DIR}/../icon.ico
) )
add_executable(${PROJECT_NAME} WIN32 ${app_WINRC} ${SOURCE_FILE}) add_executable(${PROJECT_NAME} ${app_WINRC} ${SOURCE_FILE})
add_custom_command( TARGET ${PROJECT_NAME} add_custom_command( TARGET ${PROJECT_NAME}
COMMAND echo * > ${CMAKE_BINARY_DIR}/.gitignore COMMAND echo * > ${CMAKE_BINARY_DIR}/.gitignore
COMMAND echo **/* > ${CMAKE_BINARY_DIR}/.hgignore) COMMAND echo **/* > ${CMAKE_BINARY_DIR}/.hgignore)

View File

@ -1,7 +1,99 @@
#include "MyItem.h"
#include "LyricsParser.h" #include "LyricsParser.h"
#include "MyMediaPlayer.h"
#include <cstdio> #include <cstdio>
#include <cstring>
void get_lyrics(const char *lyrics_file, int time, char *lyric_string) #define lyrics_max_length 1024
static FILE *lyrics_file = NULL;
void update_lyrics(MyMediaPlayer *player)
{ {
// Get position between filename and extension
int point_pos;
char *current_filename = my_media_player_get_filename(player);
for(int i = strlen(current_filename) - 1; i > 0; i--)
{
if(current_filename[i] == '.'){
point_pos = i;
break;
}
}
} // Get Lyrics file name
char lyric_filename[path_max_length];
strncpy(lyric_filename, current_filename, point_pos);
strncat(lyric_filename, ".lrc", 4);
// Open the lyrics file
lyrics_file = fopen(lyric_filename, "r");
}
static void get_lyrics(gint64 curr_time, gboolean playing, MyMediaPlayer *player)
{
char lyrics_line[lyrics_max_length];
static gboolean line_read = FALSE;
gint64 lyric_time = 0;
// Get lyrics data
if(lyrics_file != NULL)
{
if(playing && !line_read)
{
// Get lyrics time
fgets(lyrics_line, lyrics_max_length, lyrics_file);
gint64 lyric_min = (lyrics_line[1] - '0') * 10 +
(lyrics_line[2] - '0');
gint64 lyric_sec = (lyrics_line[4] - '0') * 10 +
(lyrics_line[5] - '0');
lyric_time = (lyrics_line[7] - '0') * 100 +
(lyrics_line[8] - '0') * 10 +
(lyrics_line[9] - '0') +
lyric_sec * 1000 +
lyric_min * 1000 * 60;
g_print("%lld\n", lyric_time);
line_read = TRUE;
}
}else{
gtk_label_set_markup(my_media_player_get_lyrics_widget(player),
"<span color=\"red\" size='12pt'>No Lyric File Found!</span>");
}
}
static void get_media_stream_status(GtkMediaStream *stream)
{
if(gtk_media_stream_get_ended(stream))
{
fclose(lyrics_file);
g_print("Media ended");
}
}
gboolean lyric_time_func(gpointer data)
{
MyMediaPlayer *player = MYMEDIA_PLAYER(data);
// if music is loaded, try to get timestamp
if (my_media_player_get_music_loaded(player))
{
// Get media stream
GtkMediaStream *stream;
stream = gtk_video_get_media_stream(GTK_VIDEO(
my_media_player_get_video_widget(player)));
// only get timestamp when media stream vaild
if (GTK_IS_MEDIA_STREAM(stream))
{
// get timestamp
gint64 timestamp = gtk_media_stream_get_timestamp(stream);
gint64 timestamp_ms = timestamp / 1000;
gboolean media_playing = gtk_media_stream_get_playing(stream);
// Update lyrics
get_lyrics(timestamp_ms, media_playing, player);
// Check whether media stopped
get_media_stream_status(stream);
}
}
return TRUE;
}

View File

@ -1,3 +1,9 @@
#pragma once #pragma once
void get_lyrics(const char *lyrics_file, int time, char *lyric_string); #include "MyMediaPlayer.h"
// Timeout function for music played time
gboolean lyric_time_func(gpointer data);
// Update lyrics file when a music will play
void update_lyrics(MyMediaPlayer *player);

View File

@ -1,8 +1,5 @@
#include "MyItem.h" #include "MyItem.h"
#include <cstring> #include <cstring>
// File name and path limits
#define name_max_length 256
#define path_max_length 4096
struct _MyItem struct _MyItem
{ {

View File

@ -2,6 +2,10 @@
#include <gtk/gtk.h> #include <gtk/gtk.h>
// File name and path limits
#define name_max_length 256
#define path_max_length 4096
#define MY_ITEM_TYPE (my_item_get_type()) #define MY_ITEM_TYPE (my_item_get_type())
G_DECLARE_FINAL_TYPE(MyItem, my_item, MY, ITEM, GObject) G_DECLARE_FINAL_TYPE(MyItem, my_item, MY, ITEM, GObject)

View File

@ -1,16 +1,22 @@
#include "MyMediaPlayer.h" #include "MyMediaPlayer.h"
#include "LyricsParser.h"
#include "MyItem.h" #include "MyItem.h"
#include <cstring>
struct _MyMediaPlayer struct _MyMediaPlayer
{ {
GtkApplicationWindow parent_instance; GtkApplicationWindow parent_instance;
GtkWidget *video, *label_lyrics; GtkWidget *video, *label_lyrics;
GtkWidget *ctrl_box;
GtkWidget *btn_priv, *btn_play, *btn_next, *btn_stop;
GtkWidget *main_box, *btn_box; GtkWidget *main_box, *btn_box;
GtkWidget *btn_add, *btn_remove; GtkWidget *btn_add, *btn_remove;
GtkWidget *btn_load, *btn_save; GtkWidget *btn_load, *btn_save;
GtkWidget *column_view; GtkWidget *column_view;
GtkWidget *scrolled_window; GtkWidget *scrolled_window;
GListStore *music_store; GListStore *music_store;
char current_filename[path_max_length];
gboolean music_loaded;
GtkSingleSelection *music_selection; GtkSingleSelection *music_selection;
GtkListItemFactory *filename_factory; GtkListItemFactory *filename_factory;
GtkColumnViewColumn *filename_column; GtkColumnViewColumn *filename_column;
@ -77,18 +83,25 @@ static void column_view_activated(GtkColumnView *self, gint position, MyMediaPla
// Play the selected media // Play the selected media
MyItem *item; MyItem *item;
GFile *music_file; GFile *music_file;
const char *file_name;
// Get selection and open the music file
item = MY_ITEM(gtk_single_selection_get_selected_item(player->music_selection)); item = MY_ITEM(gtk_single_selection_get_selected_item(player->music_selection));
music_file = g_file_new_for_path(my_item_get_filename(item)); file_name = my_item_get_filename(item);
music_file = g_file_new_for_path(file_name);
if (music_file != NULL) if (music_file != NULL)
{ {
// Add file to video widget for play
gtk_video_set_file(GTK_VIDEO(player->video), music_file); gtk_video_set_file(GTK_VIDEO(player->video), music_file);
g_object_unref(music_file);
}
// // Check whether media stream has video // Mark the player is ready and update current file name
// if(!gtk_media_stream_has_video(stream)){ player->music_loaded = TRUE;
// gtk_widget_set_size_request(player->video, 300, 50); strncpy(player->current_filename, file_name, strlen(file_name));
// } g_object_unref(music_file);
// Update lyrics file
update_lyrics(player);
}
} }
static void filename_factory_setup(GtkListItemFactory *factory, static void filename_factory_setup(GtkListItemFactory *factory,
@ -116,6 +129,30 @@ static void filename_factory_bind(GtkListItemFactory *factory,
my_item_get_dispname(file_item)); my_item_get_dispname(file_item));
} }
gboolean my_media_player_get_music_loaded(MyMediaPlayer *self)
{
// Get whether music is loaded
return self->music_loaded;
}
GtkWidget *my_media_player_get_video_widget(MyMediaPlayer *self)
{
// Get video widget
return self->video;
}
GtkLabel *my_media_player_get_lyrics_widget(MyMediaPlayer *self)
{
// Get Label for lyrics
return GTK_LABEL(self->label_lyrics);
}
char *my_media_player_get_filename(MyMediaPlayer *self)
{
// Get file name
return self->current_filename;
}
static void my_media_player_init(MyMediaPlayer *self) static void my_media_player_init(MyMediaPlayer *self)
{ {
// Initalize window // Initalize window
@ -163,6 +200,10 @@ static void my_media_player_init(MyMediaPlayer *self)
gtk_column_view_append_column(GTK_COLUMN_VIEW(self->column_view), gtk_column_view_append_column(GTK_COLUMN_VIEW(self->column_view),
self->filename_column); self->filename_column);
// Add a timer for music playing
self->music_loaded = FALSE;
g_timeout_add(1, lyric_time_func, self);
// Add widgets // Add widgets
gtk_box_append(GTK_BOX(self->main_box), self->video); gtk_box_append(GTK_BOX(self->main_box), self->video);
gtk_box_append(GTK_BOX(self->main_box), self->label_lyrics); gtk_box_append(GTK_BOX(self->main_box), self->label_lyrics);

View File

@ -4,4 +4,12 @@
G_DECLARE_FINAL_TYPE(MyMediaPlayer, my_media_player, MYMEDIA, PLAYER, GtkApplicationWindow) G_DECLARE_FINAL_TYPE(MyMediaPlayer, my_media_player, MYMEDIA, PLAYER, GtkApplicationWindow)
gboolean my_media_player_get_music_loaded(MyMediaPlayer *self);
GtkWidget *my_media_player_get_video_widget(MyMediaPlayer *self);
GtkLabel *my_media_player_get_lyrics_widget(MyMediaPlayer *self);
char *my_media_player_get_filename(MyMediaPlayer *self);
MyMediaPlayer *my_media_player_new(GtkApplication *app); MyMediaPlayer *my_media_player_new(GtkApplication *app);