<commit_before>/*
 * Copyright (C) 2010 <NAME> <<EMAIL>>.
 *
 * Author: <NAME> <<EMAIL>>
 *
 * This file is part of Rygel.
 *
 * Rygel is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Rygel 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser 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.
 */

internal errordomain MediaArtStoreError {
    NO_DIR,
    NO_MEDIA_ART
}

public class Rygel.MediaArtStore : GLib.Object {
    private const string PLACEHOLDER_HASH = "7215ee9c7d9dc229d2921a40e899ec5f";
    private const string invalid_chars = "()[]<>{}_!@#$^&*+=|\\/\"'?~";
    private const string convert_chars = "\t";
    private const string block_pattern = "%s[^%s]*%s";
    private const string[] blocks = { "()", "{}", "[]", "<>" };
    private static MediaArtStore media_art_store;
    private static bool first_time = true;
    private Regex char_remove_regex;
    private Regex char_convert_regex;
    private Regex space_compress_regex;
    private Regex[] block_regexes;

    private string directory;

    private MediaArtStore () throws MediaArtStoreError {
        var dir = Path.build_filename (Environment.get_user_cache_dir (),
                                       "media-art");
        var file = File.new_for_path (dir);

        if (!file.query_exists (null)) {
            var message = _("Failed to find media-art directory");

            throw new MediaArtStoreError.NO_DIR (message);
        }

        this.directory = dir;
        try {
            var regex_string = Regex.escape_string (invalid_chars);
            char_remove_regex = new Regex ("[%s]".printf (regex_string));
            regex_string = Regex.escape_string (convert_chars);
            char_convert_regex = new Regex ("[%s]".printf (regex_string));
            space_compress_regex = new Regex ("\\s+");
            block_regexes = new Regex[0];

            foreach (var block in blocks) {
                var block_re = block_pattern.printf (
                                  Regex.escape_string ("%C".printf (block[0])),
                                  Regex.escape_string ("%C".printf (block[1])),
                                  Regex.escape_string ("%C".printf (block[1])));
                block_regexes += new Regex (block_re);
            }
        } catch (RegexError error) {
            assert_not_reached ();
        }
    }

    public static MediaArtStore? get_default () {
        if (first_time) {
            try {
                media_art_store = new MediaArtStore ();
            } catch (MediaArtStoreError error) {
                warning (_("No media art available: %s"), error.message);
            }
        }

        first_time = false;

        return media_art_store;
    }

    public Thumbnail? find_media_art_any (MediaItem item) throws Error {
        var thumb = find_media_art (item);
        if (thumb == null) {
            thumb = find_media_art (item, true);
        }

        return thumb;
    }

    public File get_media_art_file (string    type,
                                    MediaItem item,
                                    bool      simple = false) {
        string hash;

        if (simple) {
            hash = get_simple_hash (type, item);
        } else {
            hash = get_hash (type, item);
        }
        var file_path = "%s-%s.jpeg".printf (type, hash);

        var path = Path.build_filename (this.directory, file_path);

        return File.new_for_path (path);
    }

    private string normalize_and_hash (string? input, bool utf8_only = true) {
        string normalized = " ";
        if (input != null && input != "") {
            if (utf8_only) {
                normalized = input;
            } else {
                normalized = albumart_strip_invalid_entities (input);
            }
            normalized = normalized.normalize (-1, NormalizeMode.ALL);
        }

        return Checksum.compute_for_string (ChecksumType.MD5,
                                            normalized.down ());
    }

    private string get_simple_hash (string type, MediaItem item) {
        string hash;
        switch (type) {
            case "artist":
                case "radio":
                hash = normalize_and_hash (item.author);
                break;
            case "podcast":
                hash = normalize_and_hash (item.title);
                break;
            case "album":
                hash = normalize_and_hash (item.author + "\t" +
                        item.album);
                break;
            case "track":
                hash = normalize_and_hash (item.author + "\t" +<commit_msg>core: Fix album art spec for banshee<commit_after>/*
 * Copyright (C) 2010 <NAME> <<EMAIL>>.
 *
 * Author: <NAME> <<EMAIL>>
 *
 * This file is part of Rygel.
 *
 * Rygel is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Rygel 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser 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.
 */

internal errordomain MediaArtStoreError {
    NO_DIR,
    NO_MEDIA_ART
}

public class Rygel.MediaArtStore : GLib.Object {
    private const string PLACEHOLDER_HASH = "7215ee9c7d9dc229d2921a40e899ec5f";
    private const string invalid_chars = "()[]<>{}_!@#$^&*+=|\\/\"'?~";
    private const string convert_chars = "\t";
    private const string block_pattern = "%s[^%s]*%s";
    private const string[] blocks = { "()", "{}", "[]", "<>" };
    private static MediaArtStore media_art_store;
    private static bool first_time = true;
    private Regex char_remove_regex;
    private Regex char_convert_regex;
    private Regex space_compress_regex;
    private Regex[] block_regexes;

    private string directory;

    private MediaArtStore () throws MediaArtStoreError {
        var dir = Path.build_filename (Environment.get_user_cache_dir (),
                                       "media-art");
        var file = File.new_for_path (dir);

        if (!file.query_exists (null)) {
            var message = _("Failed to find media-art directory");

            throw new MediaArtStoreError.NO_DIR (message);
        }

        this.directory = dir;
        try {
            var regex_string = Regex.escape_string (invalid_chars);
            char_remove_regex = new Regex ("[%s]".printf (regex_string));
            regex_string = Regex.escape_string (convert_chars);
            char_convert_regex = new Regex ("[%s]".printf (regex_string));
            space_compress_regex = new Regex ("\\s+");
            block_regexes = new Regex[0];

            foreach (var block in blocks) {
                var block_re = block_pattern.printf (
                                  Regex.escape_string ("%C".printf (block[0])),
                                  Regex.escape_string ("%C".printf (block[1])),
                                  Regex.escape_string ("%C".printf (block[1])));
                block_regexes += new Regex (block_re);
            }
        } catch (RegexError error) {
            assert_not_reached ();
        }
    }

    public static MediaArtStore? get_default () {
        if (first_time) {
            try {
                media_art_store = new MediaArtStore ();
            } catch (MediaArtStoreError error) {
                warning (_("No media art available: %s"), error.message);
            }
        }

        first_time = false;

        return media_art_store;
    }

    public Thumbnail? find_media_art_any (MediaItem item) throws Error {
        var thumb = find_media_art (item);
        if (thumb == null) {
            thumb = find_media_art (item, true);
        }

        return thumb;
    }

    public File get_media_art_file (string    type,
                                    MediaItem item,
                                    bool      simple = false) {
        string hash;
        string suffix = "jpeg";

        if (simple) {
            hash = get_simple_hash (type, item);
            suffix = "jpg";
        } else {
            hash = get_hash (type, item);
        }
        var file_path = "%s-%s.%s".printf (type, hash, suffix);

        var path = Path.build_filename (this.directory, file_path);

        return File.new_for_path (path);
    }

    private string normalize_and_hash (string? input, bool utf8_only = true) {
        string normalized = " ";
        if (input != null && input != "") {
            if (utf8_only) {
                normalized = input;
            } else {
                normalized = albumart_strip_invalid_entities (input);
                normalized = normalized.down ();
            }
            normalized = normalized.normalize (-1, NormalizeMode.ALL);
        }

        return Checksum.compute_for_string (ChecksumType.MD5, normalized);
    }

    private string get_simple_hash (string type, MediaItem item) {
        string hash;
        switch (type) {
            case "artist":
                case "radio":
                hash = normalize_and_hash (item.author);
                break;
            case "podcast":
                hash = normalize_and_hash (item.title);
                break;
            case "album":
                hash = normalize_and_hash (item.author + "\t" +
                        item.album);
                break;
            case "track":
                hash = normalize_and_hash (item.author + "\t" +
{'fraction_non_alphanumeric': 0.09994228549442093, 'fraction_numerical': 0.008464794151596768, 'mean_word_length': 1.9123249299719889, 'pattern_counts': {'":': 10, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5547194', 'n_tokens_mistral': 2928, 'n_tokens_neox': 2784, 'n_words': 840}