IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

GTK+ avec Python Discussion :

GdkPixbuf-CRITICAL : GDK_IS_PIXBUF_ANIMATION (animation) failed


Sujet :

GTK+ avec Python

  1. #1
    Membre habitué
    Inscrit en
    Mai 2008
    Messages
    317
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 317
    Points : 135
    Points
    135
    Par défaut GdkPixbuf-CRITICAL : GDK_IS_PIXBUF_ANIMATION (animation) failed
    Bonjour à tous.

    Je fais actuellement un petit widget de bureau en python qui permet de lire un dossier de GIF.
    Le but étant de faire un mini diaporama, sans être en plein écran, et de passer au GIF suivant après X lecture de celui ci (et non pas toutes les x secondes)

    Dans l'ensemble, le widget est terminé et fonctionne comme je le souhaite, ou presque:

    J'ai, une erreur qui pop de manière complètement aléatoire et qui plante l'application:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    (widget.py:10729): GdkPixbuf-CRITICAL **: gdk_pixbuf_animation_get_width: assertion 'GDK_IS_PIXBUF_ANIMATION (animation)' failed
    (widget.py:10729): GdkPixbuf-CRITICAL **: gdk_pixbuf_animation_get_height: assertion 'GDK_IS_PIXBUF_ANIMATION (animation)' failed
    (widget.py:10729): GdkPixbuf-CRITICAL **: gdk_pixbuf_animation_get_iter: assertion 'GDK_IS_PIXBUF_ANIMATION (animation)' failed
    (widget.py:10729): GdkPixbuf-CRITICAL **: gdk_pixbuf_animation_iter_get_delay_time: assertion 'GDK_IS_PIXBUF_ANIMATION_ITER (iter)' failed
    (widget.py:10729): GdkPixbuf-CRITICAL **: gdk_pixbuf_animation_iter_get_pixbuf: assertion 'GDK_IS_PIXBUF_ANIMATION_ITER (iter)' failed
    widget.py:230: Warning: g_object_ref: assertion 'G_IS_OBJECT (object)' failed
      Gtk.main()
    (widget.py:10729): GdkPixbuf-CRITICAL **: gdk_pixbuf_get_n_channels: assertion 'GDK_IS_PIXBUF (pixbuf)' failed
    (widget.py:10729): GdkPixbuf-CRITICAL **: gdk_pixbuf_get_height: assertion 'GDK_IS_PIXBUF (pixbuf)' failed
    (widget.py:10729): GdkPixbuf-CRITICAL **: gdk_pixbuf_get_width: assertion 'GDK_IS_PIXBUF (pixbuf)' failed
    **
    Gdk:ERROR:/tmp/buildd/gtk+3.0-3.14.5/./gdk/gdkcairo.c:193:gdk_cairo_surface_paint_pixbuf: assertion failed: (cairo_image_surface_get_format (surface) == CAIRO_FORMAT_RGB24 || cairo_image_surface_get_format (surface) == CAIRO_FORMAT_ARGB32)
    Abandon
    Je dis aléatoire par-ce que ça ne dépends pas du GIF traité, ni depuis combien de temps le programme tourne (des fois c'est au bout de 2min, des fois au bout de 2h)
    Du coup je suis complètement perdu sur ce coup, et je n'arrive pas non plus a catcher l'erreur pour passer a l'itération suivante.

    Si vous avez des idées je suis prenneur.

    Voici le code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
     
    """
    version 1.0
    """
     
    import gi
    gi.require_version('Gtk', '3.0')
    from gi.repository import Gtk, GdkPixbuf, GLib, Gio, Gdk
     
    import base64, signal, os, urllib, urllib2, time
     
    import subprocess
    import re
    import threading
     
    from PIL import Image
     
    DEBUG = True
    PATH = "/chemin/vers/mon/dossier/gif"
     
    class MainWin(Gtk.Window):
        def __init__(self):
            Gtk.Window.__init__(self, skip_pager_hint=True, skip_taskbar_hint=True)
     
            self.connect("destroy", lambda q: Gtk.main_quit())
            self.set_wmclass("sildesktopwidget","sildesktopwidget")
            self.set_type_hint(Gdk.WindowTypeHint.DOCK)
            self.set_decorated(False)
     
            self.trayIcon = TrayIcon(self)
            self.screen = Gdk.Screen.get_default()
     
            self.gifs = [os.path.join(dp, f) for dp, dn, filenames in os.walk(PATH) for f in filenames if os.path.splitext(f)[1] == '.gif']
            self.gifCounter = 0
     
            self.image = Gtk.Image()
            self.loaded = False
            self.loadNextGif()
     
            # Thread permetant de changer d'image automatiquement
            threading.Thread(target=self.getImage).start()
     
            self.image.show()
     
            self.eventBox = Gtk.EventBox()
            self.eventBox.add(self.image)
            self.eventBox.connect("button-press-event", self.eventHandler)
     
            self.fixed = Gtk.Fixed()
            self.fixed.put(self.eventBox, 0, 0)
            self.add(self.fixed)
            self.fixed.show()
     
        def getImage(self):
            while True:
                if self.loaded:
                    self.resize(1, 1)
                    self.readingImageSize = self.imageSize
                    log("------------")
                    log("getImage 1 : %s" % (self.nextGifPixbuf))
                    log(self.readingImageSize)
                    log(self.gifDuration)
     
                    try:
                        self.image.set_from_animation(self.nextGifPixbuf)
                    except:
                        log("/!\\ ERREUR INNATENDUE /!\\")
                        log(sys.exc_info()[0])
     
                    log("getImage 2")
                    self.move((self.screen.width() - self.readingImageSize[0]), (self.screen.height()) - (self.readingImageSize[1] + 48))
                    self.resize(self.readingImageSize[0], self.readingImageSize[1])
     
                    log("getImage 3")
     
                    # Thread pour pre-charger le prochain gif afin d'eviter le clipping au changement d'image par self.image.set_from_file
                    threading.Thread(target=self.loadNextGif).start()
     
                    # Determiner le nombre de lecture du gif selon sa duree
                    if self.gifDuration < 5:
                        gifDuration = self.gifDuration * 4
                    elif self.gifDuration < 10:
                        gifDuration = self.gifDuration * 2
                    else:
                        gifDuration = self.gifDuration
                    # On met en pause le temps de la lecture avant de passer au prochain gif
                    time.sleep(gifDuration)
     
                else:
                    # On verifie si l'image a bien terminee de chargee, sinon on met en pause pour 2s supplementaire
                    log("/!\\ IMAGE NON CHARGEE, pause pour 2s /!\\")
                    time.sleep(2)
     
        def loadNextGif(self):
            self.loaded = False
            log("loadNextGif 1")
     
            while self.loaded == False:
                nextGif = self.gifs[self.gifCounter % len(self.gifs)]
                self.gifCounter += 1
                log("next gif (%s) \"%s\" loading..." % (self.gifCounter % len(self.gifs) ,nextGif))
                log("loadNextGif 2")
     
                im = Image.open(nextGif)
                log("loadNextGif 3")
                if not im.info['version'].__contains__('GIF') or not im.info.has_key('duration'):
                    log("ERROR")
                    log("isGif: %s" % im.info['version'].__contains__('GIF'))
                    log("hasDuration: %s" % im.info.has_key('duration'))
                    im.close()
                    continue
                else:
                    log("loadNextGif 4")
                    n_frames = 0
                    current = im.tell()
                    try:
                        while True:
                            im.seek(im.tell() + 1)
                    except EOFError:
                        n_frames = im.tell() + 1
                    im.seek(current)
     
                    log("loadNextGif 5")
                    self.gifDuration =  float(im.info['duration'] * n_frames) / 1000
                    log("loadNextGif 6")
                    self.nextGifPixbuf = GdkPixbuf.PixbufAnimation.new_from_file(nextGif)
                    self.imageSize = im.size
                    im.close()
                    log("loadNextGif 7")
                    self.loaded = True
                    log("next gif is loaded")
     
     
        def eventHandler(self, widget, event):
            self.toggle_show()
     
        def toggle_show(self):
            if self.is_visible():
                self.hide()
                self.trayIcon._icon.set_from_file(os.path.join(
                    os.path.realpath(os.path.dirname(__file__)),
                    "images/bjmme.png"
                ))
            else:
                self.show_all()
                self.move((self.screen.width() - self.readingImageSize[0]), (self.screen.height()) - (self.readingImageSize[1] + 48))
                self.resize(1, 1)
                self.trayIcon._icon.set_from_stock(Gtk.STOCK_DIALOG_WARNING)
     
     
     
    class TrayIcon(object):
     
        """Default TrayIcon class."""
     
        def __init__(self, window, statusicon=None):
            self._icon = statusicon or self._create_statusicon()
            self._window = window
            self._conn_left = None
            self._conn_right = None
            self.show()
     
        @classmethod
        def _create_statusicon(self):
            statusicon = Gtk.StatusIcon()
            statusicon.set_from_file(os.path.join(
                os.path.realpath(os.path.dirname(__file__)),
                "images/bjmme.png"
            ))
            return statusicon
     
        @property
        def visible(self):
            """Return visibility state of icon."""
            return bool(self._conn_left)
     
        def show(self, show=True):
            """Show or hide the tray icon."""
            if show:
                if not self.visible:
                    self._show()
            else:
                self.hide()
     
        def _show(self):
            """Show the tray icon."""
            self._icon.set_visible(True)
            self._conn_left = self._icon.connect("activate", self.toggle_show)
            self._conn_right = self._icon.connect("popup-menu", self.create_context_menu)
     
        def _hide(self):
            """Hide the tray icon."""
            self._icon.set_visible(False)
            self._icon.disconnect(self._conn_left)
            self._icon.disconnect(self._conn_right)
            self._conn_left = None
            self._conn_right = None
     
        def create_context_menu(self, icon, button, time):
            """Create the context menu."""
            self.menu = Gtk.Menu()
            self.menuQuit = Gtk.MenuItem("Quit")
            self.menuQuit.connect("activate", self.quit)
     
            self.menu.append(Gtk.MenuItem())
            self.menu.append(self.menuQuit)
     
            self.menu.show_all()
            self.menu.popup(None, None, None, None, button, time)
            pass
     
        def quit(self, event):
            Gtk.main_quit()
     
        def toggle_show(self, icon):
            self._window.toggle_show()
     
        def setNew(self):
            self._icon.set_from_stock(Gtk.STOCK_REFRESH)
     
     
    def log(string):
        if DEBUG:
            print string
     
    if __name__ == '__main__':
        MainWin()
        signal.signal(signal.SIGINT, signal.SIG_DFL) # make ^c work
        Gtk.main()
    d'après ce que je comprends, c'est la ligne 71 (self.image.set_from_animation(self.nextGifPixbuf)) qui génère le problème. Mais le try/except ne fonctionne pas.
    Pourtant quand je verifie le type de self.nextGifPixbuf est bien de type PixbufAnimation.

    Bref, je sais pas trop comment m'en sortir.
    Merci

  2. #2
    Membre habitué
    Inscrit en
    Mai 2008
    Messages
    317
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 317
    Points : 135
    Points
    135
    Par défaut
    Hello,

    Bon, j'ai continuer de regarder un peu.
    J'ai remarqué que le bug ne se produisait que lorsque l'image était affichée.
    J'ai donc tenté de modifier (l.65)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    self.image.set_from_animation(self.nextGifPixbuf)
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    self.image.hide()
    self.image.set_from_animation(self.nextGifPixbuf)
    self.image.show()
    Et en effet l'application est bien plus stable (aucune idée de pourquoi mais bon, ça avance)

    Cependant, un nouveau bug apparaît de temps à autre, bien moins fréquemment que l'ancien.

    (widget.py:19423): Gdk-WARNING **: widget.py: Fatal IO error 11 (Ressource temporairement non disponible) on X server :0.0.
    Avec un peu de recherche, ce bug est déjà plus fréquent, et j'ai pu trouver quelques informations, notamment que GTK+ n'est pas thread-safe : on ne peut pas manipuler des objets GTK+ ailleurs qu'à partir du thread principal.
    Je pense donc qu'en effet la piste est de ce coté, mais je cherche encore comment faire autrement.

    J'imagine que dans mon cas, le "Thread principal" c'est ma fonction __init__ de ma class MainWin(Gtk.Window) ?

    Quelques piste sur comment faire ?

Discussions similaires

  1. Réponses: 23
    Dernier message: 17/03/2011, 17h50
  2. Animation Background Fail !
    Par dutom007 dans le forum jQuery
    Réponses: 1
    Dernier message: 29/09/2010, 11h31
  3. [Composants][Animation] Lire une vidéo compressée
    Par femtosa dans le forum Composants VCL
    Réponses: 6
    Dernier message: 03/09/2002, 08h03
  4. Rx Controls Gif animés
    Par toufou dans le forum Composants VCL
    Réponses: 6
    Dernier message: 23/08/2002, 14h09
  5. Passage de parametre a une anim Flash 5
    Par debug dans le forum Intégration
    Réponses: 4
    Dernier message: 03/06/2002, 17h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo