~ubuntu-branches/ubuntu/precise/gnash/precise-proposed

« back to all changes in this revision

Viewing changes to .pc/fixtypos.patch/libcore/parser/SWFMovieDefinition.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Angel Abad, Angel Abad, Micah Gersten
  • Date: 2010-11-28 22:18:48 UTC
  • mfrom: (3.1.10 sid)
  • Revision ID: james.westby@ubuntu.com-20101128221848-apjipwy78m13612a
Tags: 0.8.8-6ubuntu1
[ Angel Abad <angelabad@ubuntu.com> ]
* Merge from debian unstable (LP: #682386). Remaining changes:
  - Add Ubuntu flash alternatives in postinst and prerm
    + update debian/browser-plugin-gnash.postinst
    + update debian/browser-plugin-gnash.prerm

[ Micah Gersten <micahg@ubuntu.com> ]
* Only install the flash alternative in /usr/lib/mozilla/plugins as the other
  locations are deprecated
  - update debian/browser-plugin-gnash.postinst

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// SWFMovieDefinition.cpp: load a SWF definition
2
 
//
3
 
//   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
4
 
//   Foundation, Inc
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 3 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
 
//
20
 
 
21
 
#ifdef HAVE_CONFIG_H
22
 
#include "gnashconfig.h" // USE_SWFTREE
23
 
#endif
24
 
 
25
 
#include "SWFMovieDefinition.h"
26
 
 
27
 
#include <boost/bind.hpp>
28
 
#include <boost/version.hpp>
29
 
#include <boost/thread.hpp>
30
 
#include <iomanip>
31
 
#include <memory>
32
 
#include <string>
33
 
#include <algorithm> // std::make_pair
34
 
 
35
 
#include "GnashSleep.h"
36
 
#include "smart_ptr.h" // GNASH_USE_GC
37
 
#include "movie_definition.h" // for inheritance
38
 
#include "zlib_adapter.h"
39
 
#include "IOChannel.h" // for use
40
 
#include "SWFStream.h"
41
 
#include "GnashImageJpeg.h"
42
 
#include "RunResources.h"
43
 
#include "Font.h"
44
 
#include "VM.h"
45
 
#include "log.h"
46
 
#include "SWFMovie.h"
47
 
#include "GnashException.h" // for parser exception
48
 
#include "ControlTag.h"
49
 
#include "sound_definition.h" // for sound_sample
50
 
#include "GnashAlgorithm.h"
51
 
#include "SWFParser.h"
52
 
#include "Global_as.h"
53
 
#include "namedStrings.h"
54
 
#include "as_function.h"
55
 
#include "CachedBitmap.h"
56
 
 
57
 
// Debug frames load
58
 
#undef DEBUG_FRAMES_LOAD
59
 
 
60
 
// Define this this to load movies using a separate thread
61
 
// (undef and it will fully load a movie before starting to play it)
62
 
#define LOAD_MOVIES_IN_A_SEPARATE_THREAD 1
63
 
 
64
 
// Debug threads locking
65
 
//#undef DEBUG_THREADS_LOCKING
66
 
 
67
 
// Define this to get debugging output for symbol library use
68
 
//#define DEBUG_EXPORTS
69
 
 
70
 
namespace gnash
71
 
{
72
 
 
73
 
SWFMovieLoader::SWFMovieLoader(SWFMovieDefinition& md)
74
 
    :
75
 
    _movie_def(md),
76
 
    _thread(NULL),
77
 
    _barrier(2) // us and the main thread..
78
 
{
79
 
}
80
 
 
81
 
SWFMovieLoader::~SWFMovieLoader()
82
 
{
83
 
    // we should assert _movie_def._loadingCanceled
84
 
    // but we're not friend yet (anyone introduce us ?)
85
 
    if ( _thread.get() )
86
 
    {
87
 
        //cout << "Joining thread.." << endl;
88
 
        _thread->join();
89
 
    }
90
 
}
91
 
 
92
 
bool
93
 
SWFMovieLoader::started() const
94
 
{
95
 
    boost::mutex::scoped_lock lock(_mutex);
96
 
 
97
 
    return _thread.get() != NULL;
98
 
}
99
 
 
100
 
bool
101
 
SWFMovieLoader::isSelfThread() const
102
 
{
103
 
    boost::mutex::scoped_lock lock(_mutex);
104
 
 
105
 
    if (!_thread.get()) {
106
 
        return false;
107
 
    }
108
 
#if BOOST_VERSION < 103500
109
 
    boost::thread this_thread;
110
 
    return this_thread == *_thread;
111
 
#else
112
 
    return boost::this_thread::get_id() == _thread->get_id();
113
 
#endif
114
 
 
115
 
}
116
 
 
117
 
// static..
118
 
void
119
 
SWFMovieLoader::execute(SWFMovieLoader& ml, SWFMovieDefinition* md)
120
 
{
121
 
    ml._barrier.wait(); // let _thread assignment happen before going on
122
 
    md->read_all_swf();
123
 
}
124
 
 
125
 
bool
126
 
SWFMovieLoader::start()
127
 
{
128
 
#ifndef LOAD_MOVIES_IN_A_SEPARATE_THREAD
129
 
    std::abort();
130
 
#endif
131
 
    // don't start SWFMovieLoader thread() which rely
132
 
    // on boost::thread() returning before they are executed. Therefore,
133
 
    // we must employ locking.
134
 
    // Those tests do seem a bit redundant, though...
135
 
    boost::mutex::scoped_lock lock(_mutex);
136
 
 
137
 
    _thread.reset(new boost::thread(boost::bind(
138
 
                    execute, boost::ref(*this), &_movie_def)));
139
 
 
140
 
    _barrier.wait(); // let execution start befor returning
141
 
 
142
 
    return true;
143
 
}
144
 
 
145
 
 
146
 
//
147
 
// SWFMovieDefinition
148
 
//
149
 
 
150
 
SWFMovieDefinition::SWFMovieDefinition(const RunResources& runResources)
151
 
    :
152
 
    m_frame_rate(30.0f),
153
 
    m_frame_count(0u),
154
 
    m_version(0),
155
 
    _frames_loaded(0u),
156
 
    _waiting_for_frame(0),
157
 
    m_loading_sound_stream(-1),
158
 
    m_file_length(0),
159
 
    m_jpeg_in(0),
160
 
    _loader(*this),
161
 
    _loadingCanceled(false),
162
 
    _runResources(runResources),
163
 
    _as3(false)
164
 
{
165
 
}
166
 
 
167
 
SWFMovieDefinition::~SWFMovieDefinition()
168
 
{
169
 
    // Request cancelation of the loading thread
170
 
    _loadingCanceled = true;
171
 
}
172
 
 
173
 
void
174
 
SWFMovieDefinition::addDisplayObject(boost::uint16_t id, SWF::DefinitionTag* c)
175
 
{
176
 
    assert(c);
177
 
    boost::mutex::scoped_lock lock(_dictionaryMutex);
178
 
    _dictionary.addDisplayObject(id, c);
179
 
    addControlTag(c);
180
 
}
181
 
 
182
 
SWF::DefinitionTag*
183
 
SWFMovieDefinition::getDefinitionTag(boost::uint16_t id) const
184
 
{
185
 
 
186
 
    boost::mutex::scoped_lock lock(_dictionaryMutex);
187
 
 
188
 
    boost::intrusive_ptr<SWF::DefinitionTag> ch = 
189
 
        _dictionary.getDisplayObject(id);
190
 
#ifndef GNASH_USE_GC
191
 
    assert(ch == NULL || ch->get_ref_count() > 1);
192
 
#endif 
193
 
    return ch.get(); 
194
 
}
195
 
 
196
 
void
197
 
SWFMovieDefinition::add_font(int font_id, Font* f)
198
 
{
199
 
    assert(f);
200
 
    m_fonts.insert(std::make_pair(font_id, boost::intrusive_ptr<Font>(f)));
201
 
}
202
 
 
203
 
Font*
204
 
SWFMovieDefinition::get_font(int font_id) const
205
 
{
206
 
 
207
 
    FontMap::const_iterator it = m_fonts.find(font_id);
208
 
    if ( it == m_fonts.end() ) return NULL;
209
 
    boost::intrusive_ptr<Font> f = it->second;
210
 
    assert(f->get_ref_count() > 1);
211
 
    return f.get();
212
 
}
213
 
 
214
 
Font*
215
 
SWFMovieDefinition::get_font(const std::string& name, bool bold, bool italic)
216
 
    const
217
 
{
218
 
 
219
 
    for (FontMap::const_iterator it=m_fonts.begin(), itEnd=m_fonts.end(); it != itEnd; ++it)
220
 
    {
221
 
       Font* f = it->second.get();
222
 
       if ( f->matches(name, bold, italic) ) return f;
223
 
    }
224
 
    return 0;
225
 
}
226
 
 
227
 
CachedBitmap*
228
 
SWFMovieDefinition::getBitmap(int id) const
229
 
{
230
 
    const Bitmaps::const_iterator it = _bitmaps.find(id);
231
 
    if (it == _bitmaps.end()) return 0;
232
 
    return it->second.get();
233
 
}
234
 
 
235
 
void
236
 
SWFMovieDefinition::addBitmap(int id, boost::intrusive_ptr<CachedBitmap> im)
237
 
{
238
 
    assert(im);
239
 
    _bitmaps.insert(std::make_pair(id, im));
240
 
}
241
 
 
242
 
sound_sample*
243
 
SWFMovieDefinition::get_sound_sample(int id) const
244
 
{
245
 
    SoundSampleMap::const_iterator it = m_sound_samples.find(id);
246
 
    if ( it == m_sound_samples.end() ) return 0;
247
 
 
248
 
    boost::intrusive_ptr<sound_sample> ch = it->second;
249
 
#ifndef GNASH_USE_GC
250
 
    assert(ch->get_ref_count() > 1);
251
 
#endif 
252
 
 
253
 
    return ch.get();
254
 
}
255
 
 
256
 
void SWFMovieDefinition::add_sound_sample(int id, sound_sample* sam)
257
 
{
258
 
    assert(sam);
259
 
    IF_VERBOSE_PARSE(
260
 
    log_parse(_("Add sound sample %d assigning id %d"),
261
 
        id, sam->m_sound_handler_id);
262
 
    )
263
 
    m_sound_samples.insert(std::make_pair(id,
264
 
                boost::intrusive_ptr<sound_sample>(sam)));
265
 
}
266
 
 
267
 
// Read header and assign url
268
 
bool
269
 
SWFMovieDefinition::readHeader(std::auto_ptr<IOChannel> in,
270
 
        const std::string& url)
271
 
{
272
 
 
273
 
    _in = in;
274
 
 
275
 
    // we only read a movie once
276
 
    assert(!_str.get());
277
 
 
278
 
    _url = url.empty() ? "<anonymous>" : url;
279
 
 
280
 
    boost::uint32_t file_start_pos = _in->tell();
281
 
    boost::uint32_t header = _in->read_le32();
282
 
    m_file_length = _in->read_le32();
283
 
    _swf_end_pos = file_start_pos + m_file_length;
284
 
 
285
 
    m_version = (header >> 24) & 255;
286
 
    if ((header & 0x0FFFFFF) != 0x00535746
287
 
        && (header & 0x0FFFFFF) != 0x00535743)
288
 
        {
289
 
        // ERROR
290
 
        log_error(_("gnash::SWFMovieDefinition::read() -- "
291
 
            "file does not start with a SWF header"));
292
 
        return false;
293
 
        }
294
 
    const bool compressed = (header & 255) == 'C';
295
 
 
296
 
    IF_VERBOSE_PARSE(
297
 
        log_parse(_("version: %d, file_length: %d"), m_version, m_file_length);
298
 
    )
299
 
 
300
 
    if (m_version > 7)
301
 
    {
302
 
        log_unimpl(_("SWF%d is not fully supported, trying anyway "
303
 
            "but don't expect it to work"), m_version);
304
 
    }
305
 
 
306
 
    if (compressed) {
307
 
#ifndef HAVE_ZLIB_H
308
 
        log_error(_("SWFMovieDefinition::read(): unable to read "
309
 
            "zipped SWF data; gnash was compiled without zlib support"));
310
 
        return false;
311
 
#else
312
 
        IF_VERBOSE_PARSE(
313
 
            log_parse(_("file is compressed"));
314
 
        );
315
 
 
316
 
        // Uncompress the input as we read it.
317
 
        _in = zlib_adapter::make_inflater(_in);
318
 
#endif
319
 
    }
320
 
 
321
 
    assert(_in.get());
322
 
 
323
 
    _str.reset(new SWFStream(_in.get()));
324
 
 
325
 
    m_frame_size.read(*_str);
326
 
    // If the SWFRect is malformed, SWFRect::read would already 
327
 
    // print an error. We check again here just to give 
328
 
    // the error are better context.
329
 
    if ( m_frame_size.is_null() )
330
 
    {
331
 
        IF_VERBOSE_MALFORMED_SWF(
332
 
        log_swferror("non-finite movie bounds");
333
 
        );
334
 
    }
335
 
 
336
 
    _str->ensureBytes(2 + 2); // frame rate, frame count.
337
 
    m_frame_rate = _str->read_u16() / 256.0f;
338
 
    if (!m_frame_rate) {
339
 
        m_frame_rate = std::numeric_limits<boost::uint16_t>::max();
340
 
    }
341
 
 
342
 
    m_frame_count = _str->read_u16();
343
 
 
344
 
    // TODO: This seems dangerous, check closely
345
 
    if (!m_frame_count) ++m_frame_count;
346
 
 
347
 
    IF_VERBOSE_PARSE(
348
 
        log_parse(_("frame size = %s, frame rate = %f, frames = %d"),
349
 
            m_frame_size, m_frame_rate, m_frame_count);
350
 
    );
351
 
 
352
 
    setBytesLoaded(_str->tell());
353
 
    return true;
354
 
}
355
 
 
356
 
// Fire up the loading thread
357
 
bool
358
 
SWFMovieDefinition::completeLoad()
359
 
{
360
 
 
361
 
    // should call this only once
362
 
    assert( ! _loader.started() );
363
 
 
364
 
    // should call readHeader before this
365
 
    assert(_str.get());
366
 
 
367
 
#ifdef LOAD_MOVIES_IN_A_SEPARATE_THREAD
368
 
 
369
 
    // Start the loading frame
370
 
    if ( ! _loader.start() )
371
 
    {
372
 
        log_error(_("Could not start loading thread"));
373
 
        return false;
374
 
    }
375
 
 
376
 
    // Wait until 'startup_frames' have been loaded
377
 
#if 1
378
 
    size_t startup_frames = 0;
379
 
#else
380
 
    size_t startup_frames = m_frame_count;
381
 
#endif
382
 
    ensure_frame_loaded(startup_frames);
383
 
 
384
 
#else // undef LOAD_MOVIES_IN_A_SEPARATE_THREAD
385
 
 
386
 
    read_all_swf();
387
 
#endif
388
 
 
389
 
    return true;
390
 
}
391
 
 
392
 
 
393
 
// 1-based frame number
394
 
bool
395
 
SWFMovieDefinition::ensure_frame_loaded(size_t framenum) const
396
 
{
397
 
    boost::mutex::scoped_lock lock(_frames_loaded_mutex);
398
 
 
399
 
#ifndef LOAD_MOVIES_IN_A_SEPARATE_THREAD
400
 
    return (framenum <= _frames_loaded);
401
 
#endif
402
 
 
403
 
    if ( framenum <= _frames_loaded ) return true;
404
 
 
405
 
    _waiting_for_frame = framenum;
406
 
 
407
 
    // TODO: return false on timeout
408
 
    _frame_reached_condition.wait(lock);
409
 
 
410
 
    return ( framenum <= _frames_loaded );
411
 
}
412
 
 
413
 
Movie*
414
 
SWFMovieDefinition::createMovie(Global_as& gl, DisplayObject* parent)
415
 
{
416
 
    as_object* o = getObjectWithPrototype(gl, NSV::CLASS_MOVIE_CLIP);
417
 
    return new SWFMovie(o, this, parent);
418
 
}
419
 
 
420
 
 
421
 
//
422
 
// CharacterDictionary
423
 
//
424
 
 
425
 
std::ostream&
426
 
operator<<(std::ostream& o, const CharacterDictionary& cd)
427
 
{
428
 
 
429
 
       for (CharacterDictionary::CharacterConstIterator it = cd.begin(), 
430
 
            endIt = cd.end(); it != endIt; it++)
431
 
       {
432
 
           o << std::endl
433
 
             << "Character: " << it->first
434
 
             << " at address: " << static_cast<void*>(it->second.get());
435
 
       }
436
 
       
437
 
       return o;
438
 
}
439
 
 
440
 
boost::intrusive_ptr<SWF::DefinitionTag>
441
 
CharacterDictionary::getDisplayObject(int id) const
442
 
{
443
 
    CharacterConstIterator it = _map.find(id);
444
 
    if ( it == _map.end() )
445
 
    {
446
 
        IF_VERBOSE_PARSE(
447
 
            log_parse(_("Could not find char %d, dump is: %s"), id, *this);
448
 
        );
449
 
        return boost::intrusive_ptr<SWF::DefinitionTag>();
450
 
    }
451
 
    
452
 
    return it->second;
453
 
}
454
 
 
455
 
void
456
 
CharacterDictionary::addDisplayObject(int id,
457
 
        boost::intrusive_ptr<SWF::DefinitionTag> c)
458
 
{
459
 
    _map[id] = c;
460
 
}
461
 
 
462
 
 
463
 
void
464
 
SWFMovieDefinition::read_all_swf()
465
 
{
466
 
    assert(_str.get());
467
 
 
468
 
#ifdef LOAD_MOVIES_IN_A_SEPARATE_THREAD
469
 
    assert( _loader.isSelfThread() );
470
 
    assert( _loader.started() );
471
 
#else
472
 
    assert( ! _loader.started() );
473
 
    assert( ! _loader.isSelfThread() );
474
 
#endif
475
 
 
476
 
    SWFParser parser(*_str, this, _runResources);
477
 
 
478
 
    const size_t startPos = _str->tell();
479
 
    assert (startPos <= _swf_end_pos);
480
 
 
481
 
    size_t left = _swf_end_pos - startPos;
482
 
 
483
 
    const size_t chunkSize = 65535;
484
 
 
485
 
    try {
486
 
        while (left) {
487
 
 
488
 
            if (_loadingCanceled) {
489
 
                log_debug("Loading thread cancelation requested, "
490
 
                        "returning from read_all_swf");
491
 
                return;
492
 
            }
493
 
            if (!parser.read(std::min<size_t>(left, chunkSize))) break;
494
 
            
495
 
            left -= parser.bytesRead();
496
 
            setBytesLoaded(startPos + parser.bytesRead());
497
 
        }
498
 
 
499
 
        // Make sure we won't leave any pending writers
500
 
        // on any eventual fd-based IOChannel.
501
 
        _str->consumeInput();
502
 
    
503
 
    }
504
 
    catch (const ParserException& e) {
505
 
        // This is a fatal parser error.
506
 
        log_error(_("Error while parsing SWF stream."));
507
 
    }
508
 
 
509
 
    // Set bytesLoaded to the current stream position unless it's greater
510
 
    // than the reported length. TODO: should we be trying to continue
511
 
    // parsing after an exception?
512
 
    setBytesLoaded(std::min<size_t>(_str->tell(), _swf_end_pos));
513
 
 
514
 
    size_t floaded = get_loading_frame();
515
 
    if (!m_playlist[floaded].empty())
516
 
    {
517
 
        IF_VERBOSE_MALFORMED_SWF(
518
 
        log_swferror(_("%d control tags are NOT followed by"
519
 
            " a SHOWFRAME tag"), m_playlist[floaded].size());
520
 
        );
521
 
    }
522
 
 
523
 
    if ( m_frame_count > floaded )
524
 
    {
525
 
        IF_VERBOSE_MALFORMED_SWF(
526
 
        log_swferror(_("%d frames advertised in header, but only %d "
527
 
                "SHOWFRAME tags found in stream. Pretending we loaded "
528
 
                "all advertised frames"), m_frame_count, floaded);
529
 
        );
530
 
        boost::mutex::scoped_lock lock(_frames_loaded_mutex);
531
 
        _frames_loaded = m_frame_count;
532
 
        // Notify any thread waiting on frame reached condition
533
 
        _frame_reached_condition.notify_all();
534
 
    }
535
 
}
536
 
 
537
 
size_t
538
 
SWFMovieDefinition::get_loading_frame() const
539
 
{
540
 
    boost::mutex::scoped_lock lock(_frames_loaded_mutex);
541
 
    return _frames_loaded;
542
 
}
543
 
 
544
 
void
545
 
SWFMovieDefinition::incrementLoadedFrames()
546
 
{
547
 
    boost::mutex::scoped_lock lock(_frames_loaded_mutex);
548
 
 
549
 
    ++_frames_loaded;
550
 
 
551
 
    if ( _frames_loaded > m_frame_count )
552
 
    {
553
 
        IF_VERBOSE_MALFORMED_SWF(
554
 
            log_swferror(_("number of SHOWFRAME tags "
555
 
                "in SWF stream '%s' (%d) exceeds "
556
 
                "the advertised number in header (%d)."),
557
 
                get_url(), _frames_loaded,
558
 
                m_frame_count);
559
 
        )
560
 
    }
561
 
 
562
 
#ifdef DEBUG_FRAMES_LOAD
563
 
    log_debug(_("Loaded frame %u/%u"), _frames_loaded, m_frame_count);
564
 
#endif
565
 
 
566
 
    // signal load of frame if anyone requested it
567
 
    // FIXME: _waiting_for_frame needs mutex ?
568
 
    if (_waiting_for_frame && _frames_loaded >= _waiting_for_frame )
569
 
    {
570
 
        // or should we notify_one ?
571
 
        // See: http://boost.org/doc/html/condition.html
572
 
        _frame_reached_condition.notify_all();
573
 
    }
574
 
 
575
 
}
576
 
 
577
 
void
578
 
SWFMovieDefinition::registerExport(const std::string& symbol,
579
 
        boost::uint16_t id)
580
 
{
581
 
    assert(id);
582
 
 
583
 
    boost::mutex::scoped_lock lock(_exportedResourcesMutex);
584
 
#ifdef DEBUG_EXPORTS
585
 
    log_debug("%s registering export %s, %s", get_url(), symbol, id);
586
 
#endif
587
 
    _exportTable[symbol] = id;
588
 
}
589
 
 
590
 
 
591
 
void
592
 
SWFMovieDefinition::add_frame_name(const std::string& n)
593
 
{
594
 
    boost::mutex::scoped_lock lock1(_namedFramesMutex);
595
 
    boost::mutex::scoped_lock lock2(_frames_loaded_mutex);
596
 
 
597
 
    _namedFrames.insert(std::make_pair(n, _frames_loaded));
598
 
}
599
 
 
600
 
bool
601
 
SWFMovieDefinition::get_labeled_frame(const std::string& label,
602
 
        size_t& frame_number) const
603
 
{
604
 
    boost::mutex::scoped_lock lock(_namedFramesMutex);
605
 
    NamedFrameMap::const_iterator it = _namedFrames.find(label);
606
 
    if (it == _namedFrames.end()) return false;
607
 
    frame_number = it->second;
608
 
    return true;
609
 
}
610
 
 
611
 
 
612
 
boost::uint16_t
613
 
SWFMovieDefinition::exportID(const std::string& symbol) const
614
 
{
615
 
    boost::mutex::scoped_lock lock(_exportedResourcesMutex);
616
 
    Exports::const_iterator it = _exportTable.find(symbol);
617
 
    return (it == _exportTable.end()) ? 0 : it->second;
618
 
}
619
 
 
620
 
 
621
 
void
622
 
SWFMovieDefinition::importResources(
623
 
        boost::intrusive_ptr<movie_definition> source, const Imports& imports)
624
 
{
625
 
    size_t importedSyms = 0;
626
 
 
627
 
    // Mutex scope.
628
 
 
629
 
    for (Imports::const_iterator i = imports.begin(), e = imports.end(); i != e;
630
 
            ++i) {
631
 
    
632
 
        size_t new_loading_frame = source->get_loading_frame();
633
 
        
634
 
        // 0.1 seconds.
635
 
        const size_t naptime = 100000;
636
 
 
637
 
        // Timeout after two seconds of NO frames progress
638
 
        const size_t timeout_ms = 2000000;
639
 
        const size_t def_timeout = timeout_ms / naptime; 
640
 
 
641
 
        size_t timeout = def_timeout;
642
 
        size_t loading_frame = (size_t)-1; // used to keep track of advancements
643
 
 
644
 
        const int id = i->first;
645
 
        const std::string& symbolName = i->second;
646
 
 
647
 
#ifdef DEBUG_EXPORTS
648
 
        log_debug("%s importing %s from %s", get_url(), symbolName,
649
 
                source->get_url());
650
 
#endif
651
 
        boost::uint16_t targetID;
652
 
 
653
 
        while(!(targetID = source->exportID(symbolName))) {
654
 
            
655
 
            // We checked last (or past-last) advertised frame. 
656
 
            // TODO: this check should really be for a parser
657
 
            //       process being active or not, as SWF
658
 
            //       might advertise less frames then actually
659
 
            //       found in it...
660
 
            //
661
 
            if (new_loading_frame >= source->get_frame_count()) {
662
 
                // Update of loading_frame is
663
 
                // really just for the latter debugging output
664
 
                loading_frame = new_loading_frame;
665
 
                break;
666
 
            }
667
 
 
668
 
            // There's more frames to parse, go ahead
669
 
            // TODO: this is still based on *advertised*
670
 
            //       number of frames, if SWF advertises
671
 
            //       more then actually found we'd be
672
 
            //       keep trying till timeout, see the
673
 
            //       other TODO above.
674
 
 
675
 
            // We made frame progress since last iteration
676
 
            // so sleep some and try again
677
 
            if (new_loading_frame != loading_frame) {
678
 
#ifdef DEBUG_EXPORTS
679
 
                log_debug(_("looking for exported resource: frame load "
680
 
                            "advancement (from %d to %d)"),
681
 
                    loading_frame, new_loading_frame);
682
 
#endif
683
 
                loading_frame = new_loading_frame;
684
 
                timeout = def_timeout+1;
685
 
            }
686
 
            else if (!--timeout) {
687
 
                // no progress since last run, and 
688
 
                // timeout reached: give up
689
 
                break;
690
 
            }
691
 
 
692
 
            // take a breath to give other threads more time to advance
693
 
            gnashSleep(naptime);
694
 
 
695
 
        }
696
 
 
697
 
        // timed out
698
 
        if (!timeout) {
699
 
            log_error("Timeout (%d milliseconds) seeking export "
700
 
                "symbol %s in movie %s. Frames loaded %d/%d",
701
 
                timeout_ms / 1000, symbolName,
702
 
                source->get_url(), loading_frame, source->get_frame_count());
703
 
            continue;
704
 
        }
705
 
        else {
706
 
            // eof
707
 
            //assert(loading_frame >= m_frame_count);
708
 
            log_error("No export symbol %s found in movie %s. "
709
 
                "Frames loaded %d/%d",
710
 
                symbolName, source->get_url(), loading_frame,
711
 
                source->get_frame_count());
712
 
        }
713
 
 
714
 
        boost::intrusive_ptr<SWF::DefinitionTag> res =
715
 
            source->getDefinitionTag(targetID);
716
 
        if (res) {
717
 
            // It's a character import.
718
 
            addDisplayObject(id, res.get());
719
 
            registerExport(symbolName, id);
720
 
            ++importedSyms;
721
 
            continue;
722
 
        }
723
 
 
724
 
        Font* f = source->get_font(id);
725
 
        if (f) {
726
 
            // It's a font import
727
 
            add_font(id, f);
728
 
            registerExport(symbolName, id);
729
 
            ++importedSyms;
730
 
            continue;
731
 
        }
732
 
        log_error(_("import error: could not find resource '%s' in "
733
 
                    "movie '%s'"), symbolName, source->get_url());
734
 
    }
735
 
 
736
 
    if (importedSyms) {
737
 
        _importSources.insert(source);
738
 
    }
739
 
}
740
 
 
741
 
} // namespace gnash