initial commit
[goodguy/history.git] / cinelerra-5.0 / cinelerra / indexstate.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2009 Adam Williams <broadcast at earthling dot net>
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22
23 #include "asset.h"
24 #include "filexml.h"
25 #include "format.inc"
26 #include "indexstate.h"
27 #include "indexstate.inc"
28 #include "language.h"
29
30 #include <stdio.h>
31
32
33 IndexState::IndexState()
34 {
35         reset();
36 }
37
38 IndexState::~IndexState()
39 {
40         delete [] index_offsets;
41         delete [] index_sizes;
42 // Don't delete index buffer since it is shared with the index thread.
43 }
44
45 void IndexState::reset()
46 {
47         index_status = INDEX_NOTTESTED;
48         index_start = old_index_end = index_end = 0;
49         index_offsets = 0;
50         index_sizes = 0;
51         index_zoom = 0;
52         index_bytes = 0;
53         index_buffer = 0;
54         channels = 0;
55 }
56
57 void IndexState::dump()
58 {
59         printf("IndexState::dump this=%p\n", this);
60         printf("    channels=%d index_status=%d index_zoom=" _LD
61                 " index_bytes=" _LD " index_offsets=%p\n",
62                 channels, index_status, index_zoom,
63                 index_bytes, index_offsets);
64         if(index_sizes)
65         {
66                 printf("    index_sizes=");
67                 for(int i = 0; i < channels; i++)
68                         printf(_LD " ", index_sizes[i]);
69                 printf("\n");
70         }
71 }
72
73 void IndexState::copy_from(IndexState *src)
74 {
75         if(this == src) return;
76
77         delete [] index_offsets;
78         delete [] index_sizes;
79         index_offsets = 0;
80         index_sizes = 0;
81
82 //printf("Asset::update_index 1 %d\n", index_status);
83         index_status = src->index_status;
84         index_zoom = src->index_zoom;    // zoom factor of index data
85         index_start = src->index_start;  // byte start of index data in the index file
86         index_bytes = src->index_bytes;  // Total bytes in source file for comparison before rebuilding the index
87         index_end = src->index_end;
88         old_index_end = src->old_index_end;      // values for index build
89         channels = src->channels;
90
91         if(src->index_offsets)
92         {
93                 index_offsets = new int64_t[channels];
94                 index_sizes = new int64_t[channels];
95
96                 int i;
97                 for(i = 0; i < channels; i++)
98                 {
99 // offsets of channels in index file in floats
100                         index_offsets[i] = src->index_offsets[i];  
101                         index_sizes[i] = src->index_sizes[i];
102                 }
103         }
104
105 // pointer
106         index_buffer = src->index_buffer;
107 }
108
109 void IndexState::write_xml(FileXML *file)
110 {
111         file->tag.set_title("INDEX");
112         file->tag.set_property("ZOOM", index_zoom);
113         file->tag.set_property("BYTES", index_bytes);
114         file->append_tag();
115         file->append_newline();
116
117         if(index_offsets)
118         {
119                 for(int i = 0; i < channels; i++)
120                 {
121                         file->tag.set_title("OFFSET");
122                         file->tag.set_property("FLOAT", index_offsets[i]);
123                         file->append_tag();
124                         file->tag.set_title("SIZE");
125                         file->tag.set_property("FLOAT", index_sizes[i]);
126                         file->append_tag();
127                 }
128         }
129
130         file->append_newline();
131         file->tag.set_title("/INDEX");
132         file->append_tag();
133         file->append_newline();
134 }
135
136 void IndexState::read_xml(FileXML *file, int channels)
137 {
138         this->channels = channels;
139
140         delete [] index_offsets;
141         delete [] index_sizes;
142         index_offsets = new int64_t[channels];
143         index_sizes = new int64_t[channels];
144
145         for(int i = 0; i < channels; i++) 
146         {
147                 index_offsets[i] = 0;
148                 index_sizes[i] = 0;
149         }
150
151         int current_offset = 0;
152         int current_size = 0;
153         int result = 0;
154
155         index_zoom = file->tag.get_property("ZOOM", 1);
156         index_bytes = file->tag.get_property("BYTES", (int64_t)0);
157
158         while(!result)
159         {
160                 result = file->read_tag();
161                 if(!result)
162                 {
163                         if(file->tag.title_is("/INDEX"))
164                         {
165                                 result = 1;
166                         }
167                         else
168                         if(file->tag.title_is("OFFSET"))
169                         {
170                                 if(current_offset < channels)
171                                 {
172                                         index_offsets[current_offset++] = file->tag.get_property("FLOAT", 0);
173 //printf("Asset::read_index %d %d\n", current_offset - 1, index_offsets[current_offset - 1]);
174                                 }
175                         }
176                         else
177                         if(file->tag.title_is("SIZE"))
178                         {
179                                 if(current_size < channels)
180                                 {
181                                         index_sizes[current_size++] = file->tag.get_property("FLOAT", 0);
182                                 }
183                         }
184                 }
185         }
186 }
187
188 int IndexState::write_index(const char *path, 
189         int data_bytes, 
190         Asset *asset,
191         int64_t length_source)
192 {
193
194         FILE *file;
195         if(!(file = fopen(path, "wb")))
196         {
197 // failed to create it
198                 printf(_("IndexState::write_index Couldn't write index file %s to disk.\n"), 
199                         path);
200         }
201         else
202         {
203                 FileXML xml;
204 // Pad index start position
205                 fwrite((char*)&(index_start), sizeof(int64_t), 1, file);
206
207                 index_status = INDEX_READY;
208
209 // Write asset encoding information in index file.
210 // This also calls back into index_state to write it.
211                 if(asset)
212                 {
213                         asset->write(&xml, 
214                                 1, 
215                                 "");
216                 }
217                 else
218                 {
219 // Must write index_state directly.
220                         write_xml(&xml);
221                 }
222
223                 xml.write_to_file(file);
224                 index_start = ftell(file);
225                 fseek(file, 0, SEEK_SET);
226 // Write index start
227                 fwrite((char*)&(index_start), sizeof(int64_t), 1, file);
228                 fseek(file, index_start, SEEK_SET);
229
230 // Write index data
231                 fwrite(index_buffer, 
232                         data_bytes, 
233                         1, 
234                         file);
235                 fclose(file);
236         }
237
238 // Force reread of header
239         index_status = INDEX_NOTTESTED;
240         index_end = length_source;
241         old_index_end = 0;
242         index_start = 0;
243         return 0;
244 }
245
246 int64_t IndexState::get_index_offset(int channel)
247 {
248         return channel < channels && index_offsets ? index_offsets[channel] : 0;
249 }
250
251 int64_t IndexState::get_index_size(int channel)
252 {
253         return channel < channels && index_sizes ? index_sizes[channel] : 0;
254 }
255
256