2021-02-12 12:56:41 +02:00
/* file.c
*
* Copyright 2021 Joshua Strobl
*
* Licensed under the Apache License , Version 2.0 ( the " License " ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
*/
# include <glib-2.0/glib.h>
2021-03-02 19:12:12 +02:00
# include <sqlite3.h>
2021-02-16 17:15:10 +02:00
# include <taglib/tag_c.h>
2021-03-23 19:50:09 +02:00
# include "../db/cartographer.h"
2021-03-02 19:12:12 +02:00
# include "structs.h"
2021-02-16 17:15:10 +02:00
# include "koto-utils.h"
2021-02-12 12:56:41 +02:00
2021-05-11 20:05:04 +03:00
extern KotoCartographer * koto_maps ;
extern sqlite3 * koto_db ;
2021-03-02 19:12:12 +02:00
2021-03-16 08:51:35 +02:00
struct _KotoIndexedTrack {
2021-02-12 12:56:41 +02:00
GObject parent_instance ;
2021-05-11 20:05:04 +03:00
gchar * artist_uuid ;
gchar * album_uuid ;
gchar * uuid ;
gchar * path ;
2021-02-16 17:15:10 +02:00
2021-05-11 20:05:04 +03:00
gchar * file_name ;
gchar * parsed_name ;
guint * cd ;
guint * position ;
guint * playback_position ;
2021-03-02 19:12:12 +02:00
2021-02-12 12:56:41 +02:00
gboolean acquired_metadata_from_id3 ;
2021-03-02 19:12:12 +02:00
gboolean do_initial_index ;
2021-02-12 12:56:41 +02:00
} ;
2021-03-16 08:51:35 +02:00
G_DEFINE_TYPE ( KotoIndexedTrack , koto_indexed_track , G_TYPE_OBJECT ) ;
2021-02-12 12:56:41 +02:00
enum {
PROP_0 ,
2021-03-02 19:12:12 +02:00
PROP_ARTIST_UUID ,
PROP_ALBUM_UUID ,
PROP_UUID ,
PROP_DO_INITIAL_INDEX ,
2021-03-09 11:45:44 +02:00
PROP_PATH ,
2021-02-12 12:56:41 +02:00
PROP_FILE_NAME ,
PROP_PARSED_NAME ,
2021-02-25 18:15:36 +02:00
PROP_CD ,
2021-02-12 12:56:41 +02:00
PROP_POSITION ,
2021-03-23 19:50:09 +02:00
PROP_PLAYBACK_POSITION ,
2021-02-12 12:56:41 +02:00
N_PROPERTIES
} ;
2021-05-11 20:05:04 +03:00
static GParamSpec * props [ N_PROPERTIES ] = {
NULL
} ;
static void koto_indexed_track_get_property (
GObject * obj ,
guint prop_id ,
GValue * val ,
GParamSpec * spec
) ;
static void koto_indexed_track_set_property (
GObject * obj ,
guint prop_id ,
const GValue * val ,
GParamSpec * spec
) ;
static void koto_indexed_track_class_init ( KotoIndexedTrackClass * c ) {
GObjectClass * gobject_class ;
2021-02-12 12:56:41 +02:00
gobject_class = G_OBJECT_CLASS ( c ) ;
2021-03-16 08:51:35 +02:00
gobject_class - > set_property = koto_indexed_track_set_property ;
gobject_class - > get_property = koto_indexed_track_get_property ;
2021-02-12 12:56:41 +02:00
2021-03-02 19:12:12 +02:00
props [ PROP_ARTIST_UUID ] = g_param_spec_string (
" artist-uuid " ,
" UUID to Artist associated with the File " ,
" UUID to Artist associated with the File " ,
NULL ,
2021-05-11 20:05:04 +03:00
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
2021-03-02 19:12:12 +02:00
) ;
props [ PROP_ALBUM_UUID ] = g_param_spec_string (
" album-uuid " ,
" UUID to Album associated with the File " ,
" UUID to Album associated with the File " ,
NULL ,
2021-05-11 20:05:04 +03:00
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
2021-03-02 19:12:12 +02:00
) ;
props [ PROP_UUID ] = g_param_spec_string (
" uuid " ,
" UUID to File in database " ,
" UUID to File in database " ,
NULL ,
2021-05-11 20:05:04 +03:00
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
2021-03-02 19:12:12 +02:00
) ;
props [ PROP_DO_INITIAL_INDEX ] = g_param_spec_boolean (
" do-initial-index " ,
" Do an initial indexing operating instead of pulling from the database " ,
" Do an initial indexing operating instead of pulling from the database " ,
FALSE ,
2021-05-11 20:05:04 +03:00
G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
2021-03-02 19:12:12 +02:00
) ;
2021-02-12 12:56:41 +02:00
props [ PROP_PATH ] = g_param_spec_string (
" path " ,
" Path " ,
" Path to File " ,
NULL ,
2021-05-11 20:05:04 +03:00
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
2021-02-12 12:56:41 +02:00
) ;
props [ PROP_FILE_NAME ] = g_param_spec_string (
" file-name " ,
" Name of File " ,
" Name of File " ,
NULL ,
2021-05-11 20:05:04 +03:00
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
2021-02-12 12:56:41 +02:00
) ;
props [ PROP_PARSED_NAME ] = g_param_spec_string (
" parsed-name " ,
" Parsed Name of File " ,
" Parsed Name of File " ,
NULL ,
2021-05-11 20:05:04 +03:00
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
2021-02-12 12:56:41 +02:00
) ;
2021-02-25 18:15:36 +02:00
props [ PROP_CD ] = g_param_spec_uint (
" cd " ,
" CD the Track belongs to " ,
" CD the Track belongs to " ,
0 ,
G_MAXUINT16 ,
1 ,
2021-05-11 20:05:04 +03:00
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
2021-02-25 18:15:36 +02:00
) ;
2021-02-12 12:56:41 +02:00
props [ PROP_POSITION ] = g_param_spec_uint (
" position " ,
" Position in Audiobook, Album, etc. " ,
" Position in Audiobook, Album, etc. " ,
0 ,
G_MAXUINT16 ,
0 ,
2021-05-11 20:05:04 +03:00
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
2021-02-12 12:56:41 +02:00
) ;
2021-03-23 19:50:09 +02:00
props [ PROP_PLAYBACK_POSITION ] = g_param_spec_uint (
" playback-position " ,
" Current playback position " ,
" Current playback position " ,
0 ,
G_MAXUINT16 ,
0 ,
2021-05-11 20:05:04 +03:00
G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READWRITE
2021-03-23 19:50:09 +02:00
) ;
2021-02-12 12:56:41 +02:00
g_object_class_install_properties ( gobject_class , N_PROPERTIES , props ) ;
}
2021-05-11 20:05:04 +03:00
static void koto_indexed_track_init ( KotoIndexedTrack * self ) {
2021-02-12 12:56:41 +02:00
self - > acquired_metadata_from_id3 = FALSE ;
}
2021-05-11 20:05:04 +03:00
static void koto_indexed_track_get_property (
GObject * obj ,
guint prop_id ,
GValue * val ,
GParamSpec * spec
) {
KotoIndexedTrack * self = KOTO_INDEXED_TRACK ( obj ) ;
2021-02-12 12:56:41 +02:00
switch ( prop_id ) {
2021-03-02 19:12:12 +02:00
case PROP_ARTIST_UUID :
g_value_set_string ( val , self - > artist_uuid ) ;
break ;
case PROP_ALBUM_UUID :
g_value_set_string ( val , self - > album_uuid ) ;
break ;
case PROP_UUID :
g_value_set_string ( val , self - > uuid ) ;
break ;
2021-03-09 11:45:44 +02:00
case PROP_PATH :
g_value_set_string ( val , self - > path ) ;
break ;
2021-02-12 12:56:41 +02:00
case PROP_FILE_NAME :
g_value_set_string ( val , self - > file_name ) ;
break ;
case PROP_PARSED_NAME :
g_value_set_string ( val , self - > parsed_name ) ;
break ;
2021-02-25 18:15:36 +02:00
case PROP_CD :
g_value_set_uint ( val , GPOINTER_TO_UINT ( self - > cd ) ) ;
break ;
2021-02-12 12:56:41 +02:00
case PROP_POSITION :
2021-02-16 17:15:10 +02:00
g_value_set_uint ( val , GPOINTER_TO_UINT ( self - > position ) ) ;
2021-02-12 12:56:41 +02:00
break ;
2021-03-23 19:50:09 +02:00
case PROP_PLAYBACK_POSITION :
g_value_set_uint ( val , GPOINTER_TO_UINT ( self - > playback_position ) ) ;
break ;
2021-02-12 12:56:41 +02:00
default :
G_OBJECT_WARN_INVALID_PROPERTY_ID ( obj , prop_id , spec ) ;
break ;
}
}
2021-05-11 20:05:04 +03:00
static void koto_indexed_track_set_property (
GObject * obj ,
guint prop_id ,
const GValue * val ,
GParamSpec * spec
) {
KotoIndexedTrack * self = KOTO_INDEXED_TRACK ( obj ) ;
2021-02-12 12:56:41 +02:00
switch ( prop_id ) {
2021-03-02 19:12:12 +02:00
case PROP_ARTIST_UUID :
self - > artist_uuid = g_strdup ( g_value_get_string ( val ) ) ;
g_object_notify_by_pspec ( G_OBJECT ( self ) , props [ PROP_ARTIST_UUID ] ) ;
break ;
case PROP_ALBUM_UUID :
self - > album_uuid = g_strdup ( g_value_get_string ( val ) ) ;
g_object_notify_by_pspec ( G_OBJECT ( self ) , props [ PROP_ALBUM_UUID ] ) ;
break ;
case PROP_UUID :
self - > uuid = g_strdup ( g_value_get_string ( val ) ) ;
g_object_notify_by_pspec ( G_OBJECT ( self ) , props [ PROP_UUID ] ) ;
break ;
case PROP_DO_INITIAL_INDEX :
self - > do_initial_index = g_value_get_boolean ( val ) ;
break ;
2021-03-09 11:45:44 +02:00
case PROP_PATH :
2021-03-16 08:51:35 +02:00
koto_indexed_track_update_path ( self , g_value_get_string ( val ) ) ; // Update the path
2021-03-09 11:45:44 +02:00
break ;
2021-02-12 12:56:41 +02:00
case PROP_FILE_NAME :
2021-03-16 08:51:35 +02:00
koto_indexed_track_set_file_name ( self , g_strdup ( g_value_get_string ( val ) ) ) ; // Update the file name
2021-02-12 12:56:41 +02:00
break ;
case PROP_PARSED_NAME :
2021-03-16 08:51:35 +02:00
koto_indexed_track_set_parsed_name ( self , g_strdup ( g_value_get_string ( val ) ) ) ;
2021-02-12 12:56:41 +02:00
break ;
2021-02-25 18:15:36 +02:00
case PROP_CD :
2021-03-16 08:51:35 +02:00
koto_indexed_track_set_cd ( self , g_value_get_uint ( val ) ) ;
2021-02-25 18:15:36 +02:00
break ;
2021-02-12 12:56:41 +02:00
case PROP_POSITION :
2021-03-16 08:51:35 +02:00
koto_indexed_track_set_position ( self , g_value_get_uint ( val ) ) ;
2021-02-12 12:56:41 +02:00
break ;
2021-03-23 19:50:09 +02:00
case PROP_PLAYBACK_POSITION :
self - > playback_position = GUINT_TO_POINTER ( g_value_get_uint ( val ) ) ;
break ;
2021-02-12 12:56:41 +02:00
default :
G_OBJECT_WARN_INVALID_PROPERTY_ID ( obj , prop_id , spec ) ;
break ;
}
}
2021-03-02 19:12:12 +02:00
2021-05-11 20:05:04 +03:00
void koto_indexed_track_commit ( KotoIndexedTrack * self ) {
2021-03-02 19:12:12 +02:00
if ( ( self - > artist_uuid = = NULL ) | | ( strcmp ( self - > artist_uuid , " " ) = = 0 ) ) { // No valid required artist UUID
return ;
}
if ( self - > album_uuid = = NULL ) {
g_object_set ( self , " album-uuid " , " " , NULL ) ; // Set to an empty string
}
2021-05-11 20:05:04 +03:00
gchar * commit_op = g_strdup_printf (
2021-03-02 19:12:12 +02:00
" INSERT INTO tracks(id, path, type, artist_id, album_id, file_name, name, disc, position) "
" VALUES('%s', quote( \" %s \" ), 0, '%s', '%s', quote( \" %s \" ), quote( \" %s \" ), %d, %d) "
" ON CONFLICT(id) DO UPDATE SET path=excluded.path, type=excluded.type, album_id=excluded.album_id, file_name=excluded.file_name, name=excluded.file_name, disc=excluded.disc, position=excluded.position; " ,
self - > uuid ,
self - > path ,
self - > artist_uuid ,
self - > album_uuid ,
self - > file_name ,
self - > parsed_name ,
GPOINTER_TO_INT ( ( int * ) self - > cd ) ,
GPOINTER_TO_INT ( ( int * ) self - > position )
) ;
2021-05-11 20:05:04 +03:00
gchar * commit_op_errmsg = NULL ;
2021-03-02 19:12:12 +02:00
int rc = sqlite3_exec ( koto_db , commit_op , 0 , 0 , & commit_op_errmsg ) ;
2021-05-11 20:05:04 +03:00
2021-03-02 19:12:12 +02:00
if ( rc ! = SQLITE_OK ) {
g_warning ( " Failed to write our file to the database: %s " , commit_op_errmsg ) ;
}
g_free ( commit_op ) ;
g_free ( commit_op_errmsg ) ;
}
2021-05-11 20:05:04 +03:00
GVariant * koto_indexed_track_get_metadata_vardict ( KotoIndexedTrack * self ) {
2021-05-11 18:31:13 +03:00
if ( ! KOTO_IS_INDEXED_TRACK ( self ) ) {
return NULL ;
}
2021-05-11 20:05:04 +03:00
GVariantBuilder * builder = g_variant_builder_new ( G_VARIANT_TYPE_VARDICT ) ;
gchar * album_art_path = NULL ;
gchar * album_name = NULL ;
gchar * artist_name = NULL ;
2021-05-11 18:31:13 +03:00
2021-05-11 20:05:04 +03:00
KotoIndexedArtist * artist = koto_cartographer_get_artist_by_uuid ( koto_maps , self - > artist_uuid ) ;
KotoIndexedAlbum * album = koto_cartographer_get_album_by_uuid ( koto_maps , self - > album_uuid ) ;
2021-05-11 18:31:13 +03:00
2021-05-11 20:05:04 +03:00
g_object_get ( album , " art-path " , & album_art_path , " name " , & album_name , NULL ) ;
2021-05-11 18:31:13 +03:00
2021-05-11 20:05:04 +03:00
g_object_get ( artist , " name " , & artist_name , NULL ) ;
2021-05-11 18:31:13 +03:00
g_variant_builder_add ( builder , " {sv} " , " mpris:trackid " , g_variant_new_string ( self - > uuid ) ) ;
if ( koto_utils_is_string_valid ( album_art_path ) ) { // Valid album art path
album_art_path = g_strconcat ( " file:// " , album_art_path , NULL ) ; // Prepend with file://
g_variant_builder_add ( builder , " {sv} " , " mpris:artUrl " , g_variant_new_string ( album_art_path ) ) ;
}
g_variant_builder_add ( builder , " {sv} " , " xesam:album " , g_variant_new_string ( album_name ) ) ;
if ( koto_utils_is_string_valid ( artist_name ) ) { // Valid artist name
2021-05-11 20:05:04 +03:00
GVariant * artist_name_variant ;
GVariantBuilder * artist_list_builder = g_variant_builder_new ( G_VARIANT_TYPE ( " as " ) ) ;
2021-05-11 18:31:13 +03:00
g_variant_builder_add ( artist_list_builder , " s " , artist_name ) ;
artist_name_variant = g_variant_new ( " as " , artist_list_builder ) ;
g_variant_builder_unref ( artist_list_builder ) ;
g_variant_builder_add ( builder , " {sv} " , " xesam:artist " , artist_name_variant ) ;
g_variant_builder_add ( builder , " {sv} " , " playbackengine:artist " , g_variant_new_string ( artist_name ) ) ; // Add a sort of "meta" string val for our playback engine so we don't need to mess about with the array
}
g_variant_builder_add ( builder , " {sv} " , " xesam:discNumber " , g_variant_new_uint64 ( GPOINTER_TO_UINT ( self - > cd ) ) ) ;
g_variant_builder_add ( builder , " {sv} " , " xesam:title " , g_variant_new_string ( self - > parsed_name ) ) ;
g_variant_builder_add ( builder , " {sv} " , " xesam:url " , g_variant_new_string ( self - > path ) ) ;
g_variant_builder_add ( builder , " {sv} " , " xesam:trackNumber " , g_variant_new_uint64 ( GPOINTER_TO_UINT ( self - > position ) ) ) ;
2021-05-11 20:05:04 +03:00
GVariant * metadata_ret = g_variant_builder_end ( builder ) ;
2021-05-11 18:31:13 +03:00
return metadata_ret ;
}
2021-05-11 20:05:04 +03:00
gchar * koto_indexed_track_get_uuid ( KotoIndexedTrack * self ) {
2021-05-07 16:45:57 +03:00
if ( ! KOTO_IS_INDEXED_TRACK ( self ) ) {
return NULL ;
}
return self - > uuid ; // Do not return a duplicate since otherwise comparison refs fail due to pointer positions being different
}
2021-05-11 20:05:04 +03:00
void koto_indexed_track_parse_name ( KotoIndexedTrack * self ) {
gchar * copied_file_name = g_strdelimit ( g_strdup ( self - > file_name ) , " _ " , ' ' ) ; // Replace _ with whitespace for starters
KotoIndexedArtist * artist = NULL ;
2021-02-16 17:15:10 +02:00
2021-03-23 19:50:09 +02:00
artist = koto_cartographer_get_artist_by_uuid ( koto_maps , self - > artist_uuid ) ;
2021-02-16 17:15:10 +02:00
2021-03-23 19:50:09 +02:00
if ( artist ! = NULL ) { // If we have artist
2021-05-11 20:05:04 +03:00
gchar * artist_name = NULL ;
2021-03-23 19:50:09 +02:00
g_object_get ( artist , " name " , & artist_name , NULL ) ;
if ( artist_name ! = NULL & & ( strcmp ( artist_name , " " ) ! = 0 ) ) {
2021-05-11 20:05:04 +03:00
gchar * * split = g_strsplit ( copied_file_name , artist_name , - 1 ) ; // Split whenever we encounter the artist
2021-03-23 19:50:09 +02:00
copied_file_name = g_strjoinv ( " " , split ) ; // Remove the artist
g_strfreev ( split ) ;
split = g_strsplit ( copied_file_name , g_utf8_strdown ( artist_name , - 1 ) , - 1 ) ; // Lowercase album name and split by that
copied_file_name = g_strjoinv ( " " , split ) ; // Remove the artist
g_strfreev ( split ) ;
}
2021-02-16 17:15:10 +02:00
}
2021-05-11 20:05:04 +03:00
gchar * file_without_ext = koto_utils_get_filename_without_extension ( copied_file_name ) ;
2021-02-16 17:15:10 +02:00
g_free ( copied_file_name ) ;
2021-05-11 20:05:04 +03:00
gchar * * split = g_regex_split_simple ( " ^([ \\ d]+) " , file_without_ext , G_REGEX_JAVASCRIPT_COMPAT , 0 ) ;
2021-02-16 17:15:10 +02:00
if ( g_strv_length ( split ) > 1 ) { // Has positional info at the beginning of the file
2021-05-11 20:05:04 +03:00
gchar * num = split [ 1 ] ;
2021-02-16 17:15:10 +02:00
g_free ( file_without_ext ) ; // Free the prior name
file_without_ext = g_strdup ( split [ 2 ] ) ; // Set to our second item which is the rest of the song name without the prefixed numbers
if ( ( strcmp ( num , " 0 " ) = = 0 ) | | ( strcmp ( num , " 00 " ) = = 0 ) ) { // Is exactly zero
2021-03-16 08:51:35 +02:00
koto_indexed_track_set_position ( self , 0 ) ; // Set position to 0
2021-02-16 17:15:10 +02:00
} else { // Either starts with 0 (like 09) or doesn't start with it at all
guint64 potential_pos = g_ascii_strtoull ( num , NULL , 10 ) ; // Attempt to convert
if ( potential_pos ! = 0 ) { // Got a legitimate position
2021-03-16 08:51:35 +02:00
koto_indexed_track_set_position ( self , potential_pos ) ;
2021-02-16 17:15:10 +02:00
}
}
}
g_strfreev ( split ) ;
2021-03-09 11:45:44 +02:00
split = g_strsplit ( file_without_ext , " - " , - 1 ) ; // Split whenever we encounter " - "
file_without_ext = g_strjoinv ( " " , split ) ; // Remove entirely
g_strfreev ( split ) ;
split = g_strsplit ( file_without_ext , " - " , - 1 ) ; // Split whenever we encounter -
file_without_ext = g_strjoinv ( " " , split ) ; // Remove entirely
g_strfreev ( split ) ;
2021-03-16 08:51:35 +02:00
koto_indexed_track_set_parsed_name ( self , file_without_ext ) ;
2021-02-16 17:15:10 +02:00
g_free ( file_without_ext ) ;
}
2021-05-11 20:05:04 +03:00
void koto_indexed_track_remove_from_playlist (
KotoIndexedTrack * self ,
gchar * playlist_uuid
) {
2021-05-07 16:45:57 +03:00
if ( ! KOTO_IS_INDEXED_TRACK ( self ) ) {
return ;
}
2021-05-11 20:05:04 +03:00
gchar * commit_op = g_strdup_printf (
2021-05-07 16:45:57 +03:00
" DELETE FROM playlist_tracks WHERE track_id='%s' AND playlist_id='%s' " ,
self - > uuid ,
playlist_uuid
) ;
2021-05-11 20:05:04 +03:00
gchar * commit_op_errmsg = NULL ;
2021-05-07 16:45:57 +03:00
int rc = sqlite3_exec ( koto_db , commit_op , 0 , 0 , & commit_op_errmsg ) ;
2021-05-11 20:05:04 +03:00
2021-05-07 16:45:57 +03:00
if ( rc ! = SQLITE_OK ) {
g_warning ( " Failed to remove track from playlist: %s " , commit_op_errmsg ) ;
}
g_free ( commit_op ) ;
g_free ( commit_op_errmsg ) ;
}
2021-05-11 20:05:04 +03:00
void koto_indexed_track_save_to_playlist (
KotoIndexedTrack * self ,
gchar * playlist_uuid ,
gint current
) {
2021-05-07 16:45:57 +03:00
if ( ! KOTO_IS_INDEXED_TRACK ( self ) ) {
return ;
}
2021-05-11 20:05:04 +03:00
gchar * commit_op = g_strdup_printf (
2021-05-07 16:45:57 +03:00
" INSERT INTO playlist_tracks(playlist_id, track_id, current) "
" VALUES('%s', '%s', quote( \" %d \" )) " ,
2021-03-23 19:50:09 +02:00
playlist_uuid ,
self - > uuid ,
current
) ;
2021-05-11 20:05:04 +03:00
gchar * commit_op_errmsg = NULL ;
2021-03-23 19:50:09 +02:00
int rc = sqlite3_exec ( koto_db , commit_op , 0 , 0 , & commit_op_errmsg ) ;
2021-05-11 20:05:04 +03:00
2021-03-23 19:50:09 +02:00
if ( rc ! = SQLITE_OK ) {
g_warning ( " Failed to save track to playlist: %s " , commit_op_errmsg ) ;
}
g_free ( commit_op ) ;
g_free ( commit_op_errmsg ) ;
}
2021-05-11 20:05:04 +03:00
void koto_indexed_track_set_file_name (
KotoIndexedTrack * self ,
gchar * new_file_name
) {
2021-02-12 12:56:41 +02:00
if ( new_file_name = = NULL ) {
return ;
}
if ( ( self - > file_name ! = NULL ) & & ( strcmp ( self - > file_name , new_file_name ) = = 0 ) ) { // Not null and the same
return ; // Don't do anything
}
if ( self - > file_name ! = NULL ) { // If it is defined
g_free ( self - > file_name ) ;
}
self - > file_name = g_strdup ( new_file_name ) ;
g_object_notify_by_pspec ( G_OBJECT ( self ) , props [ PROP_FILE_NAME ] ) ;
2021-03-09 11:45:44 +02:00
if ( ! self - > acquired_metadata_from_id3 & & self - > do_initial_index ) { // Haven't acquired our information from ID3
2021-03-16 08:51:35 +02:00
koto_indexed_track_parse_name ( self ) ; // Update our parsed name
2021-02-12 12:56:41 +02:00
}
}
2021-05-11 20:05:04 +03:00
void koto_indexed_track_set_cd (
KotoIndexedTrack * self ,
guint cd
) {
2021-02-27 17:26:24 +02:00
if ( cd = = 0 ) { // No change really
2021-02-25 18:15:36 +02:00
return ;
}
self - > cd = GUINT_TO_POINTER ( cd ) ;
g_object_notify_by_pspec ( G_OBJECT ( self ) , props [ PROP_CD ] ) ;
}
2021-05-11 20:05:04 +03:00
void koto_indexed_track_set_parsed_name (
KotoIndexedTrack * self ,
gchar * new_parsed_name
) {
2021-02-12 12:56:41 +02:00
if ( new_parsed_name = = NULL ) {
return ;
}
if ( ( self - > parsed_name ! = NULL ) & & ( strcmp ( self - > parsed_name , new_parsed_name ) = = 0 ) ) { // Not null and the same
return ; // Don't do anything
}
if ( self - > parsed_name ! = NULL ) {
g_free ( self - > parsed_name ) ;
}
self - > parsed_name = g_strdup ( new_parsed_name ) ;
g_object_notify_by_pspec ( G_OBJECT ( self ) , props [ PROP_PARSED_NAME ] ) ;
}
2021-05-11 20:05:04 +03:00
void koto_indexed_track_set_position (
KotoIndexedTrack * self ,
guint pos
) {
2021-02-16 17:15:10 +02:00
if ( pos = = 0 ) { // No position change really
return ;
2021-02-12 12:56:41 +02:00
}
2021-02-16 17:15:10 +02:00
self - > position = GUINT_TO_POINTER ( pos ) ;
g_object_notify_by_pspec ( G_OBJECT ( self ) , props [ PROP_POSITION ] ) ;
}
2021-02-12 12:56:41 +02:00
2021-05-11 20:05:04 +03:00
void koto_indexed_track_update_metadata ( KotoIndexedTrack * self ) {
TagLib_File * t_file = taglib_file_new ( self - > path ) ; // Get a taglib file for this file
2021-02-12 12:56:41 +02:00
2021-05-11 20:05:04 +03:00
if ( ( t_file ! = NULL ) & & taglib_file_is_valid ( t_file ) ) { // If we got the taglib file and it is valid
self - > acquired_metadata_from_id3 = TRUE ;
TagLib_Tag * tag = taglib_file_tag ( t_file ) ; // Get our tag
koto_indexed_track_set_parsed_name ( self , taglib_tag_title ( tag ) ) ; // Set the title of the file
koto_indexed_track_set_position ( self , ( uint ) taglib_tag_track ( tag ) ) ; // Get the track, convert to uint and cast as a pointer
koto_indexed_track_set_file_name ( self , g_path_get_basename ( self - > path ) ) ; // Update our file name
} else {
koto_indexed_track_set_file_name ( self , g_path_get_basename ( self - > path ) ) ; // Update our file name
}
taglib_tag_free_strings ( ) ; // Free strings
taglib_file_free ( t_file ) ; // Free the file
2021-02-16 17:15:10 +02:00
}
2021-02-12 12:56:41 +02:00
2021-05-11 20:05:04 +03:00
void koto_indexed_track_update_path (
KotoIndexedTrack * self ,
const gchar * new_path
) {
2021-02-16 17:15:10 +02:00
if ( new_path = = NULL ) {
return ;
2021-02-12 12:56:41 +02:00
}
2021-02-16 17:15:10 +02:00
if ( self - > path ! = NULL ) { // Already have a path
g_free ( self - > path ) ; // Free it
}
2021-02-12 12:56:41 +02:00
2021-02-16 17:15:10 +02:00
self - > path = g_strdup ( new_path ) ; // Duplicate the path and set it
2021-03-09 11:45:44 +02:00
if ( self - > do_initial_index ) {
2021-03-16 08:51:35 +02:00
koto_indexed_track_update_metadata ( self ) ; // Attempt to get ID3 info
2021-03-09 11:45:44 +02:00
}
2021-02-16 17:15:10 +02:00
g_object_notify_by_pspec ( G_OBJECT ( self ) , props [ PROP_PATH ] ) ;
2021-02-12 12:56:41 +02:00
}
2021-05-11 20:05:04 +03:00
KotoIndexedTrack * koto_indexed_track_new (
KotoIndexedAlbum * album ,
const gchar * path ,
guint * cd
) {
gchar * artist_uuid ;
gchar * album_uuid ;
2021-03-09 11:45:44 +02:00
2021-03-23 19:50:09 +02:00
g_object_get ( album , " artist-uuid " , & artist_uuid , " uuid " , & album_uuid , NULL ) ; // Get the artist and album uuids from our Album
2021-03-02 19:12:12 +02:00
2021-05-11 20:05:04 +03:00
KotoIndexedTrack * track = g_object_new (
KOTO_TYPE_INDEXED_TRACK ,
" artist-uuid " ,
artist_uuid ,
" album-uuid " ,
album_uuid ,
" do-initial-index " ,
TRUE ,
" uuid " ,
g_uuid_string_random ( ) ,
" path " ,
path ,
" cd " ,
cd ,
2021-02-12 12:56:41 +02:00
NULL
) ;
2021-03-02 19:12:12 +02:00
2021-05-11 20:05:04 +03:00
2021-03-16 08:51:35 +02:00
koto_indexed_track_commit ( track ) ; // Immediately commit to the database
return track ;
2021-03-02 19:12:12 +02:00
}
2021-05-11 20:05:04 +03:00
KotoIndexedTrack * koto_indexed_track_new_with_uuid ( const gchar * uuid ) {
return g_object_new (
KOTO_TYPE_INDEXED_TRACK ,
" uuid " ,
g_strdup ( uuid ) ,
2021-03-02 19:12:12 +02:00
NULL
) ;
2021-02-12 12:56:41 +02:00
}