1 /* Gnome Music Player Client (GMPC)
2 * Copyright (C) 2004-2012 Qball Cow <qball@gmpclient.org>
3 * Project homepage: http://gmpclient.org/
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include <libmpd/libmpd-internal.h>
32 #define LOG_DOMAIN "Gmpc.Misc"
35 * Total time: %i days %i hours %i minutes
37 gchar
*format_time(unsigned long seconds
)
40 gchar
*string
= g_strdup_printf("%s: ", _("Total time"));
41 retv
= format_time_real(seconds
, string
);
46 gchar
*format_time_real(unsigned long seconds
, const gchar
* data
)
49 int days
= seconds
/ 86400;
50 int hours
= (seconds
% 86400) / 3600;
51 int minutes
= (seconds
% 3600) / 60;
57 str
= g_string_new(data
);
60 g_string_append_printf(str
, "%i %s ", days
, ngettext("day", "days", days
));
64 g_string_append_printf(str
, "%i %s ", hours
, ngettext("hour", "hours", hours
));
68 g_string_append_printf(str
, "%i %s ", minutes
, ngettext("minute", "minutes", minutes
));
72 g_string_append_printf(str
, "%lu %s ", (seconds
%60), ngettext("second", "seconds", (seconds
%60)));
76 g_string_free(str
, FALSE
);
79 gchar
*format_time_real_newline(unsigned long seconds
, const gchar
* data
)
82 int days
= seconds
/ 86400;
83 int hours
= (seconds
% 86400) / 3600;
84 int minutes
= (seconds
% 3600) / 60;
91 str
= g_string_new(data
);
95 g_string_append_c(str
, '\n');
97 g_string_append_printf(str
, "%i %s ", days
, ngettext("day", "days", days
));
103 g_string_append_c(str
, '\n');
105 g_string_append_printf(str
, "%i %s ", hours
, ngettext("hour", "hours", hours
));
111 g_string_append_c(str
, '\n');
113 g_string_append_printf(str
, "%i %s ", minutes
, ngettext("minute", "minutes", minutes
));
116 if((seconds
%60) != 0)
119 g_string_append_c(str
, '\n');
121 g_string_append_printf(str
, "%lu %s ", (seconds
%60), ngettext("second", "seconds", (seconds
%60)));
126 g_string_free(str
, FALSE
);
131 * Wrapper around mpd_song_markup, that escapes the entries for use with pango markup
132 * You still need to make sure "markup" is pango-markup proof
134 void mpd_song_markup_escaped(char *buffer
, int size
, char *markup
, mpd_Song
* song2
)
136 mpd_Song
*song
= mpd_newSong();
139 song
->title
= g_markup_escape_text(song2
->title
, -1);
143 song
->artist
= g_markup_escape_text(song2
->artist
, -1);
145 if (song2
->albumartist
)
147 song
->albumartist
= g_markup_escape_text(song2
->albumartist
, -1);
151 song
->album
= g_markup_escape_text(song2
->album
, -1);
155 song
->track
= g_markup_escape_text(song2
->track
, -1);
159 song
->name
= g_markup_escape_text(song2
->name
, -1);
163 song
->date
= g_markup_escape_text(song2
->date
, -1);
167 song
->genre
= g_markup_escape_text(song2
->genre
, -1);
171 song
->composer
= g_markup_escape_text(song2
->composer
, -1);
175 song
->disc
= g_markup_escape_text(song2
->disc
, -1);
179 song
->comment
= g_markup_escape_text(song2
->comment
, -1);
183 song
->file
= g_markup_escape_text(song2
->file
, -1);
185 song
->id
= song2
->id
;
186 song
->pos
= song2
->pos
;
187 song
->time
= song2
->time
;
189 mpd_song_markup(buffer
, size
, markup
, song
);
194 * Code copied from gnome-screenshot
197 void screenshot_add_border(GdkPixbuf
* src
)
200 int x
, y
, width
, height
;
211 rowstride
= gdk_pixbuf_get_rowstride(pb
);
212 n_channels
= gdk_pixbuf_get_n_channels(pb
);
213 width
= gdk_pixbuf_get_width(pb
);
214 height
= gdk_pixbuf_get_height(pb
);
215 pixels
= gdk_pixbuf_get_pixels(pb
);
217 for (y
= 0; y
< height
; y
++)
219 for (x
= 0; x
< width
; x
++)
221 if (y
== 0 || y
== (height
- 1) || x
== 0 || x
== (width
- 1))
223 for (pixel
= 0; pixel
< n_channels
; pixel
++)
225 pixels
[x
* n_channels
+ y
* rowstride
+ pixel
] = 0;
233 * @param: The filename or empty, to get dir path.
235 * Function to get the full user of filename for gmpc.
236 * On unix this is ~/.config/gmpc/filename
238 * returns: an allocated string.
240 gchar
*gmpc_get_user_path(const gchar
* filename
)
242 const gchar
*homedir
= g_get_user_config_dir();
246 ret
= g_build_path(G_DIR_SEPARATOR_S
, homedir
, "gmpc", filename
, NULL
);
252 * @param: The filename or empty, to get dir path.
254 * Function to get the full user of filename for gmpc's cover.
255 * On unix this is ~/.cache/gmpc/metadata/filename
257 * returns: an allocated string.
259 gchar
*gmpc_get_covers_path(const gchar
* filename
)
261 const gchar
*homedir
= g_get_user_cache_dir();
265 ret
= g_build_path(G_DIR_SEPARATOR_S
, homedir
, "gmpc", "metadata", filename
, NULL
);
271 * @param: The filename or empty, to get dir path.
273 * Function to get the cache directory
274 * On unix this is ~/.cache/gmpc/filename
276 * returns: an allocated string.
278 gchar
*gmpc_get_cache_directory(const gchar
* filename
)
280 const gchar
*homedir
= g_get_user_cache_dir();
284 ret
= g_build_path(G_DIR_SEPARATOR_S
, homedir
, "gmpc", filename
, NULL
);
289 * Get's the full path to an image,
290 * While this is compile time on linux, windows
291 * needs to determine it run-time.
293 char *gmpc_get_full_image_path(void)
296 const gchar
*const *paths
= g_get_system_data_dirs();
299 /* First try the compile time path */
300 path
= g_build_filename(PIXMAP_PATH
, NULL
);
303 if (g_file_test(path
, G_FILE_TEST_EXISTS
| G_FILE_TEST_IS_DIR
))
311 for (i
= 0; paths
&& paths
[i
]; i
++)
313 path
= g_build_filename(paths
[i
], "gmpc", "icons", NULL
);
314 if (g_file_test(path
, G_FILE_TEST_EXISTS
| G_FILE_TEST_IS_DIR
))
323 g_error("Failed to find images");
330 * Get the full path to the glade files.
331 * While this is compile time on linux, windows
332 * needs to determine it run-time
334 char *gmpc_get_full_glade_path(const char *filename
)
337 const gchar
*const *paths
= g_get_system_data_dirs();
340 path
= g_build_filename(GLADE_PATH
, filename
, NULL
);
343 if (g_file_test(path
, G_FILE_TEST_EXISTS
))
349 for (i
= 0; paths
&& paths
[i
]; i
++)
351 path
= g_build_filename(paths
[i
], "gmpc", filename
, NULL
);
352 if (g_file_test(path
, G_FILE_TEST_EXISTS
))
361 g_error("Failed to locate glade path");
367 void open_uri(const gchar
* uri
)
371 GError
*error
= NULL
;
373 gchar
*browser_command
=
374 cfg_get_single_value_as_string_with_default(config
, "External", "browser-win32", "cmd /c start \"%s\"");
377 gchar
*browser_command
= cfg_get_single_value_as_string_with_default(config
, "External", "browser-osx", "open \"%s\"");
379 gchar
*browser_command
= cfg_get_single_value_as_string_with_default(config
, "External", "browser", "xdg-open \"%s\"");
382 gchar
*escaped_uri
= g_strescape(uri
, "");
383 command
= g_strdup_printf(browser_command
, escaped_uri
);
385 result
= g_spawn_command_line_async(command
, &error
);
389 gchar
*str
= g_markup_printf_escaped("%s: '%s': %s", _("Failed to execute"), command
, error
->message
);
390 playlist3_show_error_message(str
, ERROR_WARNING
);
395 g_free(browser_command
);
402 void open_help(const char *uri
)
405 GError
*error
= NULL
;
406 command
= g_strdup_printf("yelp %s", uri
);
407 result
= g_spawn_command_line_async(command
, &error
);
410 /* Ignore errors for now */
418 int *split_version(const char *uri
)
420 int *retv
= g_malloc0(4 * sizeof(int));
421 char **sp
= g_strsplit(uri
, ".", 4);
423 for (i
= 0; i
< 4 && sp
[i
]; i
++)
425 retv
[i
] = atoi(sp
[i
]);
431 MpdData
*misc_sort_mpddata(MpdData
* data
, GCompareDataFunc func
, void *user_data
)
436 MpdData_real
**nodes
;
442 for (node
= (MpdData_real
*) mpd_data_get_first(data
); node
;
443 node
= (MpdData_real
*) mpd_data_get_next_real((MpdData
*) node
, FALSE
))
445 TEC("Counted items");
447 nodes
= g_malloc0(i
* sizeof(MpdData_real
*));
449 node
= (MpdData_real
*) mpd_data_get_first(data
);
450 for (j
= 0; j
< i
; j
++)
453 node
= (MpdData_real
*) mpd_data_get_next_real((MpdData
*) node
, FALSE
);
455 TEC("Created array");
456 g_qsort_with_data(nodes
, i
, sizeof(MpdData_real
*), func
, user_data
);
458 nodes
[0]->prev
= NULL
;
459 nodes
[0]->next
= NULL
;
460 nodes
[0]->first
= nodes
[0];
461 for (j
= 1; j
< i
; j
++)
463 nodes
[j
]->prev
= nodes
[j
- 1];
464 nodes
[j
]->next
= NULL
;
465 nodes
[j
]->prev
->next
= nodes
[j
];
466 nodes
[j
]->first
= nodes
[0];
468 data
= (MpdData
*) nodes
[0];
470 TEC("Recreated linked list");
474 static gint
__add_sort(gpointer aa
, gpointer bb
, gpointer data
)
476 MpdData_real
*a
= *(MpdData_real
**) aa
;
477 MpdData_real
*b
= *(MpdData_real
**) bb
;
478 if (a
->type
== MPD_DATA_TYPE_DIRECTORY
&& b
->type
== MPD_DATA_TYPE_DIRECTORY
)
480 if (a
->directory
== NULL
&& b
->directory
!= NULL
)
482 else if (b
->directory
== NULL
&& a
->directory
!= NULL
)
484 else if (a
->directory
&& b
->directory
)
487 if (a
->directory
&& b
->directory
)
490 sa
= g_utf8_strdown(a
->directory
, -1);
491 sb
= g_utf8_strdown(b
->directory
, -1);
492 val
= g_utf8_collate(sa
, sb
);
497 val
= (a
== NULL
) ? ((b
== NULL
) ? 0 : -1) : 1;
502 if (a
->type
== MPD_DATA_TYPE_TAG
&& b
->type
== MPD_DATA_TYPE_TAG
)
504 if (a
->tag_type
!= b
->tag_type
)
505 return a
->tag_type
- b
->tag_type
;
506 if (a
->tag
== NULL
&& b
->tag
!= NULL
)
508 else if (b
->tag
== NULL
&& a
->tag
!= NULL
)
510 else if (a
->tag
&& b
->tag
)
513 if (a
->tag
&& b
->tag
)
516 sa
= g_utf8_strdown(a
->tag
, -1);
517 sb
= g_utf8_strdown(b
->tag
, -1);
518 val
= g_utf8_collate(sa
, sb
);
523 val
= (a
== NULL
) ? ((b
== NULL
) ? 0 : -1) : 1;
528 if (a
->type
== MPD_DATA_TYPE_SONG
&& b
->type
== MPD_DATA_TYPE_SONG
)
530 const char *artista
= NULL
;
531 const char *artistb
= NULL
;
532 if(a
->song
->albumartist
) artista
= a
->song
->albumartist
;
533 else artista
= a
->song
->artist
;
534 if(b
->song
->albumartist
) artistb
= b
->song
->albumartist
;
535 else artistb
= b
->song
->artist
;
536 /* Artist (prefer albumartist, if not use artist field */
537 if (artista
== NULL
&& artistb
!= NULL
)
539 else if (artistb
== NULL
&& artista
!= NULL
)
541 else if (artista
&& artistb
)
543 int compv
= g_utf8_collate(artista
, artistb
);
551 if (a
->song
->date
== NULL
&& b
->song
->date
!= NULL
)
553 else if (b
->song
->date
== NULL
&& a
->song
->date
!= NULL
)
555 else if (a
->song
->date
&& b
->song
->date
)
557 int compv
= atoi(a
->song
->date
) - atoi(b
->song
->date
);
562 if (a
->song
->album
== NULL
&& b
->song
->album
!= NULL
)
564 else if (b
->song
->album
== NULL
&& a
->song
->album
!= NULL
)
566 else if (a
->song
->album
&& b
->song
->album
)
568 int compv
= g_utf8_collate(a
->song
->album
, b
->song
->album
);
575 if (a
->song
->disc
== NULL
&& b
->song
->disc
!= NULL
)
577 else if (b
->song
->disc
== NULL
&& a
->song
->disc
!= NULL
)
579 else if (a
->song
->disc
&& b
->song
->disc
)
581 int compv
= g_utf8_collate(a
->song
->disc
, b
->song
->disc
);
587 if (a
->song
->track
== NULL
&& b
->song
->track
!= NULL
)
589 else if (b
->song
->track
== NULL
&& a
->song
->track
!= NULL
)
591 else if (a
->song
->track
&& b
->song
->track
)
593 int compv
= atoi(a
->song
->track
) - atoi(b
->song
->track
);
597 return a
->type
- b
->type
;
600 MpdData
*misc_sort_mpddata_by_album_disc_track(MpdData
* data
)
602 return misc_sort_mpddata(data
, (GCompareDataFunc
) __add_sort
, NULL
);
605 static gint
__sort_filename(gpointer aa
, gpointer bb
, gpointer data
)
607 MpdData_real
*a
= *(MpdData_real
**) aa
;
608 MpdData_real
*b
= *(MpdData_real
**) bb
;
610 if (a
->type
== MPD_DATA_TYPE_SONG
&& b
->type
== MPD_DATA_TYPE_SONG
)
612 if (a
->song
->file
&& b
->song
->file
)
613 return strcmp(a
->song
->file
, b
->song
->file
);
616 gchar
*chk_a
= mpd_song_checksum(a
->song
);
617 gchar
*chk_b
= mpd_song_checksum(b
->song
);
618 int retv
= strcmp(chk_a
, chk_b
);
623 } else if (a
->type
== MPD_DATA_TYPE_TAG
&& b
->type
== MPD_DATA_TYPE_TAG
)
625 if (a
->tag_type
== b
->tag_type
)
626 return strcmp(a
->tag
, b
->tag
);
628 return a
->type
- b
->type
;
631 MpdData
*misc_mpddata_remove_duplicate_songs(MpdData
* data
)
636 /* sort on file filename, this is our key */
637 node
= (MpdData_real
*) misc_sort_mpddata(data
, (GCompareDataFunc
) __sort_filename
, NULL
);
638 /* loop through it */
641 if (node
->type
== MPD_DATA_TYPE_SONG
&& node
->next
->type
== MPD_DATA_TYPE_SONG
)
643 if (__sort_filename(&node
, &(node
->next
), NULL
) == 0) //strcmp(node->song->file, node->next->song->file) == 0)
645 node
= (MpdData_real
*) mpd_data_delete_item((MpdData
*) node
);
648 } else if (node
->type
== MPD_DATA_TYPE_TAG
&& node
->next
->type
== MPD_DATA_TYPE_TAG
)
650 if (__sort_filename(&(node
), &(node
->next
), NULL
) == 0) //strcmp(node->tag, node->next->tag) == 0)
652 node
= (MpdData_real
*) mpd_data_delete_item((MpdData
*) node
);
658 return (MpdData
*) node
->first
;
661 gchar
**tokenize_string(const gchar
* string
)
663 gchar
**result
= NULL
; /* the result with tokens */
664 int i
= 0; /* position in string */
665 int br
= 0; /* number for open ()[]'s */
666 int bpos
= 0; /* begin position of the cur. token */
672 length
= strlen(string
);
673 for (i
= 0; i
<= length
; i
++)
675 /* check for opening [( */
676 if ((br
!= 0 || bpos
== i
) && (string
[i
] == '(' || string
[i
] == '[' || string
[i
] == '{'))
678 if (!br
&& bpos
== i
)
683 else if (br
&& (string
[i
] == ')' || string
[i
] == ']' || string
[i
] == '}'))
687 if (!br
&& (string
[i
+ 1] == ' ' || string
[i
+ 1] == '\0'))
693 /* if multiple spaces at begin of token skip them */
694 if (string
[i
] == ' ' && !(i
- bpos
))
696 /* if token end or string end add token to list */
697 else if ((string
[i
] == ' ' && !br
) || string
[i
] == '\0')
699 if ((bstop
- bpos
) > 0)
701 result
= g_realloc(result
, (tokens
+ 2) * sizeof(gchar
*));
702 result
[tokens
] = g_strndup(&string
[bpos
], bstop
- bpos
);
703 result
[tokens
+ 1] = NULL
;
714 void misc_header_style_set_process_containers(GtkWidget
* container
, GtkStyle
* old_style
, gpointer data
)
716 GtkStyle
*style
= container
->style
;
718 list
= gtk_container_get_children(GTK_CONTAINER(container
));
722 for (node
= g_list_first(list
); node
; node
= g_list_next(node
))
724 gtk_widget_modify_fg((GtkWidget
*) node
->data
, GTK_STATE_NORMAL
, &(style
->fg
[GTK_STATE_SELECTED
]));
725 gtk_widget_modify_text((GtkWidget
*) node
->data
, GTK_STATE_NORMAL
, &(style
->fg
[GTK_STATE_SELECTED
]));
726 if (GTK_IS_CONTAINER(node
->data
))
728 misc_header_style_set_process_containers((GtkWidget
*) node
->data
, NULL
, NULL
);
736 gboolean
misc_header_expose_event(GtkWidget
* widget
, GdkEventExpose
* event
)
738 int width
= widget
->allocation
.width
;
739 int height
= widget
->allocation
.height
;
741 gtk_paint_flat_box(widget
->style
,
743 GTK_STATE_SELECTED
, GTK_SHADOW_NONE
, &(event
->area
), widget
, "cell_odd", 0, 0, width
, height
);
744 gtk_paint_focus(widget
->style
, widget
->window
,
745 GTK_STATE_NORMAL
, &(event
->area
), widget
, "button", 0, 0, width
, height
);
749 gchar
*mpd_song_checksum_type(const mpd_Song
* song
, MetaDataType type
)
755 GChecksum
*cs
= g_checksum_new(G_CHECKSUM_SHA256
);
758 case META_ARTIST_SIMILAR
:
759 case META_ARTIST_TXT
:
760 case META_ARTIST_ART
:
762 g_checksum_update(cs
, (guchar
*) song
->artist
, -1);
766 case META_BACKDROP_ART
:
768 g_checksum_update(cs
, (guchar
*) song
->album
, -1);
770 g_checksum_update(cs
, (guchar
*) song
->artist
, -1);
773 case META_SONG_SIMILAR
:
774 case META_SONG_GUITAR_TAB
:
776 g_checksum_update(cs
, (guchar
*) song
->artist
, -1);
778 g_checksum_update(cs
, (guchar
*) song
->title
, -1);
780 case META_GENRE_SIMILAR
:
782 g_checksum_update(cs
, (guchar
*) song
->genre
, -1);
784 case META_QUERY_DATA_TYPES
:
785 case META_QUERY_NO_CACHE
:
789 retv
= g_strdup(g_checksum_get_string(cs
));
796 gchar
*mpd_song_checksum(const mpd_Song
* song
)
801 GChecksum
*cs
= g_checksum_new(G_CHECKSUM_SHA256
);
803 g_checksum_update(cs
, (guchar
*) song
->file
, -1);
805 g_checksum_update(cs
, (guchar
*) song
->artist
, -1);
807 g_checksum_update(cs
, (guchar
*) song
->title
, -1);
809 g_checksum_update(cs
, (guchar
*) song
->album
, -1);
811 g_checksum_update(cs
, (guchar
*) song
->track
, -1);
813 g_checksum_update(cs
, (guchar
*) song
->name
, -1);
815 g_checksum_update(cs
, (guchar
*) song
->date
, -1);
817 g_checksum_update(cs
, (guchar
*) song
->genre
, -1);
819 g_checksum_update(cs
, (guchar
*) song
->composer
, -1);
821 g_checksum_update(cs
, (guchar
*) song
->performer
, -1);
823 g_checksum_update(cs
, (guchar
*) song
->disc
, -1);
824 if (song
->albumartist
)
825 g_checksum_update(cs
, (guchar
*) song
->albumartist
, -1);
827 retv
= g_strdup(g_checksum_get_string(cs
));
833 /* Kudos to the gnome-panel guys. */
834 void colorshift_pixbuf(GdkPixbuf
* dest
, GdkPixbuf
* src
, int shift
)
837 gint width
, height
, has_alpha
, src_rowstride
, dest_rowstride
;
838 guchar
*target_pixels
;
839 guchar
*original_pixels
;
845 has_alpha
= gdk_pixbuf_get_has_alpha(src
);
846 width
= gdk_pixbuf_get_width(src
);
847 height
= gdk_pixbuf_get_height(src
);
848 src_rowstride
= gdk_pixbuf_get_rowstride(src
);
849 dest_rowstride
= gdk_pixbuf_get_rowstride(dest
);
850 original_pixels
= gdk_pixbuf_get_pixels(src
);
851 target_pixels
= gdk_pixbuf_get_pixels(dest
);
853 for (i
= 0; i
< height
; i
++)
855 pix_dest
= target_pixels
+ i
* dest_rowstride
;
856 pix_src
= original_pixels
+ i
* src_rowstride
;
858 for (j
= 0; j
< width
; j
++)
865 *(pix_dest
++) = CLAMP(val
, 0, 255);
868 *(pix_dest
++) = CLAMP(val
, 0, 255);
871 *(pix_dest
++) = CLAMP(val
, 0, 255);
874 *(pix_dest
++) = *(pix_src
++);
879 /* Kudos to the gnome-panel guys. */
880 void decolor_pixbuf(GdkPixbuf
* dest
, GdkPixbuf
* src
)
883 gint width
, height
, has_alpha
, src_rowstride
, dest_rowstride
;
884 guchar
*target_pixels
;
885 guchar
*original_pixels
;
890 has_alpha
= gdk_pixbuf_get_has_alpha(src
);
891 width
= gdk_pixbuf_get_width(src
);
892 height
= gdk_pixbuf_get_height(src
);
893 src_rowstride
= gdk_pixbuf_get_rowstride(src
);
894 dest_rowstride
= gdk_pixbuf_get_rowstride(dest
);
895 original_pixels
= gdk_pixbuf_get_pixels(src
);
896 target_pixels
= gdk_pixbuf_get_pixels(dest
);
897 for (i
= 0; i
< height
; i
++)
899 pix_dest
= target_pixels
+ i
* dest_rowstride
;
900 pix_src
= original_pixels
+ i
* src_rowstride
;
902 for (j
= 0; j
< width
; j
++)
908 r
= CLAMP(((r
)/3),0,255);
915 *(pix_dest
++) = *(pix_src
++);
920 void darken_pixbuf(GdkPixbuf
* dest
,guint factor
)
924 gint has_alpha
, dest_rowstride
;
925 guchar
*target_pixels
;
928 has_alpha
= gdk_pixbuf_get_has_alpha(dest
);
929 width
= gdk_pixbuf_get_width(dest
);
930 height
= gdk_pixbuf_get_height(dest
);
931 dest_rowstride
= gdk_pixbuf_get_rowstride(dest
);
932 target_pixels
= gdk_pixbuf_get_pixels(dest
);
933 for (i
= 0; i
< height
; i
++)
935 pix_dest
= target_pixels
+ i
* dest_rowstride
;
937 for (j
= 0; j
< width
; j
++)
939 *(pix_dest
++) >>= factor
;
940 *(pix_dest
++) >>= factor
;
941 *(pix_dest
++) >>= factor
;
949 static void create_directory(const gchar
* url
)
952 * Check if ~/.gmpc/ exists
953 * If not try to create it.
955 if (!g_file_test(url
, G_FILE_TEST_EXISTS
))
957 if (g_mkdir_with_parents(url
, 0700) < 0)
959 g_log(LOG_DOMAIN
, G_LOG_LEVEL_ERROR
, "Failed to create: %s\n", url
);
960 show_error_message("Failed to create config directory.");
965 * if it exists, check if it's a directory
967 if (!g_file_test(url
, G_FILE_TEST_IS_DIR
))
969 show_error_message("The config directory is not a directory.");
973 g_log(LOG_DOMAIN
, G_LOG_LEVEL_DEBUG
, "%s exist and is directory", url
);
978 * Create needed directories for mpd.
980 void create_gmpc_paths(void)
983 gchar
*url
= gmpc_get_user_path(NULL
);
984 create_directory(url
);
987 url
= gmpc_get_covers_path(NULL
);
988 create_directory(url
);
993 mpd_Song
* mpd_songDup0(const mpd_Song
*song
)
995 return (song
== NULL
)? NULL
: mpd_songDup(song
);