summaryrefslogtreecommitdiff
path: root/src/video-support/VideoSourceCollection.vala
blob: 89daad3c0cf4887e11dc36df9dba200d243f068c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/* Copyright 2016 Software Freedom Conservancy Inc.
 *
 * This software is licensed under the GNU LGPL (version 2.1 or later).
 * See the COPYING file in this distribution.
 */

public class VideoSourceCollection : MediaSourceCollection {
    public enum State {
        UNKNOWN,
        ONLINE,
        OFFLINE,
        TRASH
    }

    public override TransactionController transaction_controller {
        get {
            if (_transaction_controller == null)
                _transaction_controller = new MediaSourceTransactionController(this);

            return _transaction_controller;
        }
    }

    private TransactionController _transaction_controller = null;
    private Gee.MultiMap<uint64?, Video> filesize_to_video =
        new Gee.TreeMultiMap<uint64?, Video>(uint64_compare);

    public VideoSourceCollection() {
        base("VideoSourceCollection", get_video_key);

        get_trashcan().contents_altered.connect(on_trashcan_contents_altered);
        get_offline_bin().contents_altered.connect(on_offline_contents_altered);
    }

    protected override MediaSourceHoldingTank create_trashcan() {
        return new MediaSourceHoldingTank(this, is_video_trashed, get_video_key);
    }

    protected override MediaSourceHoldingTank create_offline_bin() {
        return new MediaSourceHoldingTank(this, is_video_offline, get_video_key);
    }

    public override MediaMonitor create_media_monitor(Workers workers, Cancellable cancellable) {
        return new VideoMonitor(cancellable);
    }

    public override bool holds_type_of_source(DataSource source) {
        return source is Video;
    }

    public override string get_typename() {
        return Video.TYPENAME;
    }

    public override bool is_file_recognized(File file) {
        return VideoReader.is_supported_video_file(file);
    }

    private void on_trashcan_contents_altered(Gee.Collection<DataSource>? added,
        Gee.Collection<DataSource>? removed) {
        trashcan_contents_altered((Gee.Collection<Video>?) added,
            (Gee.Collection<Video>?) removed);
    }

    private void on_offline_contents_altered(Gee.Collection<DataSource>? added,
        Gee.Collection<DataSource>? removed) {
        offline_contents_altered((Gee.Collection<Video>?) added,
            (Gee.Collection<Video>?) removed);
    }

    protected override MediaSource? fetch_by_numeric_id(int64 numeric_id) {
        return fetch(VideoID(numeric_id));
    }

    public static int64 get_video_key(DataSource source) {
        Video video = (Video) source;
        VideoID video_id = video.get_video_id();

        return video_id.id;
    }

    public static bool is_video_trashed(DataSource source) {
        return ((Video) source).is_trashed();
    }

    public static bool is_video_offline(DataSource source) {
        return ((Video) source).is_offline();
    }

    public Video fetch(VideoID video_id) {
        return (Video) fetch_by_key(video_id.id);
    }

    public override Gee.Collection<string> get_event_source_ids(EventID event_id){
        return VideoTable.get_instance().get_event_source_ids(event_id);
    }

    public Video? get_state_by_file(File file, out State state) {
        Video? video = (Video?) fetch_by_master_file(file);
        if (video != null) {
            state = State.ONLINE;

            return video;
        }

        video = (Video?) get_trashcan().fetch_by_master_file(file);
        if (video != null) {
            state = State.TRASH;

            return video;
        }

        video = (Video?) get_offline_bin().fetch_by_master_file(file);
        if (video != null) {
            state = State.OFFLINE;

            return video;
        }

        state = State.UNKNOWN;

        return null;
    }

    private void compare_backing(Video video, FileInfo info, Gee.Collection<Video> matching_master) {
        if (video.get_filesize() != info.get_size())
            return;

        if (video.get_timestamp().equal(info.get_modification_date_time()))
            matching_master.add(video);
    }

    public void fetch_by_matching_backing(FileInfo info, Gee.Collection<Video> matching_master) {
        foreach (DataObject object in get_all())
            compare_backing((Video) object, info, matching_master);

        foreach (MediaSource media in get_offline_bin_contents())
            compare_backing((Video) media, info, matching_master);
    }

    protected override void notify_contents_altered(Gee.Iterable<DataObject>? added,
        Gee.Iterable<DataObject>? removed) {
        if (added != null) {
            foreach (DataObject object in added) {
                Video video = (Video) object;

                filesize_to_video.set(video.get_master_filesize(), video);
            }
        }

        if (removed != null) {
            foreach (DataObject object in removed) {
                Video video = (Video) object;

                filesize_to_video.remove(video.get_master_filesize(), video);
            }
        }

        base.notify_contents_altered(added, removed);
    }

    public VideoID get_basename_filesize_duplicate(string basename, uint64 filesize) {
        foreach (Video video in filesize_to_video.get(filesize)) {
            if (utf8_ci_compare(video.get_master_file().get_basename(), basename) == 0)
                return video.get_video_id();
        }

        return VideoID(); // the default constructor of the VideoID struct creates an invalid
                          // video id, which is just what we want in this case
    }

    public bool has_basename_filesize_duplicate(string basename, uint64 filesize) {
        return get_basename_filesize_duplicate(basename, filesize).is_valid();
    }
}