summaryrefslogtreecommitdiff
path: root/src/samples/asyncload.py
blob: 48f15dbdce550cbf88bd9b69697597d98740d7c7 (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
#!/usr/bin/env python
# -*- coding: utf-8 -*-

'''
Shows how to use BitmapManager to asynchronously load a Bitmap from a file.
Run this snippet providing a list of filenames of (high resolution) pictures:

$ ./asyncload.py /path/to/mypics/*.jpg anotherpic.png nonexistent.png

Press space to sequentially load the pictures. A rotating rectangle appears
during the time the picture file is being loaded to show how the main thread
is not affected by the load operation.

Press 'f' to display the frame time graph, which should show no significant
glitches while loading
'''

import sys
from libavg import avg, player, app

APP_RESOLUTION = (640, 480)


class AsyncLoadDiv(app.MainDiv):

    def onInit(self):
        '''
        Create placeholders for the example. A single ImageNode is used to show
        the pictures.
        '''
        self.__imageNode = avg.ImageNode(pos=(10, 20), parent=self)
        self.__spinner = avg.RectNode(color='222222', fillopacity=1, size=(40, 40), 
                active=False, pos=(10, self.size.y - 50), parent=self)
        self.__infoNode = avg.WordsNode(text='Press space to load the first image',
                fontsize=11, pos=(10, 5), parent=self)
        
        self.__pics = sys.argv[1:]
        self.__currentPic = -1
        player.subscribe(player.ON_FRAME, self.__onFrame)
        app.keyboardmanager.bindKeyDown(keystring="space", handler=self.__requestNextBitmap,
                help="Request next bitmap")
    
    def __requestNextBitmap(self):
        '''
        Ask the BitmapManager to load a new file. loadBitmap() call returns immediately.
        '''
        self.__currentPic = (self.__currentPic + 1) % len(self.__pics)
        avg.BitmapManager.get().loadBitmap(self.__pics[self.__currentPic],
                self.__onBitmapLoaded)
                
        self.__spinner.active = True
        self.__spinner.angle = 0
        
    def __onBitmapLoaded(self, bmp):
        '''
        This callback is invoked by BitmapManager, 'bmp' can be either a Bitmap instance
        or a RuntimeError instance (hence checking for Exception is consistent).
        '''
        self.__spinner.active = False
        if isinstance(bmp, Exception):
            self.__infoNode.text = ('Error loading '
                    'image %s : %s' % (self.__pics[self.__currentPic], str(bmp)))
            self.__imageNode.href = ''
        else:
            self.__infoNode.text = ('Loaded %s, '
                    'press space for the next one' % self.__pics[self.__currentPic])
            self.__setBitmapAndResize(bmp)
    
    def __setBitmapAndResize(self, bmp):
        originalSize = bmp.getSize()
        
        if originalSize.x > originalSize.y:
            ratio = (APP_RESOLUTION[0] - 20) / originalSize.x
        else:
            ratio = (APP_RESOLUTION[1] - 40) / originalSize.y
        
        self.__imageNode.setBitmap(bmp)
        self.__imageNode.size = originalSize * ratio
            
    def __onFrame(self):
        if self.__spinner.active:
            self.__spinner.angle += 0.05

if len(sys.argv) == 1:
    print 'Usage: %s <filename> [<filename> [<filename> [..]]]' % sys.argv[0]
    sys.exit(1)
    
app.App().run(AsyncLoadDiv(), app_resolution="640,480")