Ejemplo n.º 1
0
    def build_action_box(self, obj_evt):
        # build the widget to present an event :
        # tooltip with event infos
        # image containing snapshot of the event
        # label with the time of the event
        act = obj_evt.name
        act_begin = time.strftime("%H:%M:%S", time.localtime(obj_evt.time[0]))
        if self.options['time'] == 'activity':
            act_begin = helper.format_time_reference(obj_evt.activity_time[0])
        entetestr = "%s : %s" % (act_begin, act)
        corpsstr = ""
        for op in obj_evt.operations:
            op_time = time.strftime("%H:%M:%S", time.localtime(op.time))
            if self.options['time'] == 'activity':
                op_time = helper.format_time_reference(op.activity_time)
            if op.concerned_object['name'] is None:
                corpsstr += urllib.parse.unquote(op_time + " : " + op.name +
                                                 "\n")
            else:
                corpsstr += urllib.parse.unquote(op_time + " : " + op.name +
                                                 " ( " +
                                                 op.concerned_object['name'] +
                                                 " : " +
                                                 op.concerned_object['id'] +
                                                 " )\n")
        entete = Gtk.Label(label=entetestr.encode("UTF-8"))
        hb = Gtk.HBox()
        box = Gtk.EventBox()
        tr = TimestampRepresentation(obj_evt.movietime, None, self.controller,
                                     50, 0, None, False)
        if tr is not None:
            hb.pack_start(tr, False, True, 0)
            hb.pack_start(Gtk.VSeparator(), False, False, 0)
        if corpsstr != "":
            hb.set_tooltip_text(corpsstr)

        def box_pressed(w, event, ops):
            if event.button == 1 and event.type == Gdk.EventType._2BUTTON_PRESS:
                #FIXME : need to change details in another way
                self.filters['objects'] = []
                self.filters['objects'].extend(ops)
                self.options['detail'] = 'operations'
                self.DetB.set_label('operations')
                #FIXME color change of the reset button when applying a filter
                self.filter_active(True)
                self.receive(self.tracer.trace)
            return

        box.add(entete)
        box.connect('button-press-event', box_pressed, obj_evt.operations)
        hb.pack_start(box, False, True, 0)
        return hb
Ejemplo n.º 2
0
    def generate_transcription(self):
        last=None
        for d in self.parse_transcription(show_ignored=True,
                                          strip_blank=False):
            if d['ignored']:
                yield '[I%s]' % helper.format_time_reference(d['begin'])
                yield d['content']
                yield '[%s]' % helper.format_time_reference(d['end'])

            elif last != d['begin']:
                yield '[%s]' % helper.format_time_reference(d['begin'])
                yield d['content']
                yield '[%s]' % helper.format_time_reference(d['end'])
            else:
                yield d['content']
                yield '[%s]' % helper.format_time_reference(d['end'])
            last=d['end']
Ejemplo n.º 3
0
    def generate_transcription(self):
        last=None
        for d in self.parse_transcription(show_ignored=True,
                                          strip_blank=False):
            if d['ignored']:
                yield '[I%s]' % helper.format_time_reference(d['begin'])
                yield d['content']
                yield '[%s]' % helper.format_time_reference(d['end'])

            elif last != d['begin']:
                yield '[%s]' % helper.format_time_reference(d['begin'])
                yield d['content']
                yield '[%s]' % helper.format_time_reference(d['end'])
            else:
                yield d['content']
                yield '[%s]' % helper.format_time_reference(d['end'])
            last=d['end']
Ejemplo n.º 4
0
 def build_action_box(self, obj_evt):
     # build the widget to present an event :
     # tooltip with event infos
     # image containing snapshot of the event
     # label with the time of the event
     act = obj_evt.name
     act_begin = time.strftime("%H:%M:%S", time.localtime(obj_evt.time[0]))
     if self.options['time'] == 'activity':
         act_begin = helper.format_time_reference(obj_evt.activity_time[0])
     entetestr = "%s : %s" % (act_begin, act)
     corpsstr = ""
     for op in obj_evt.operations:
         op_time = time.strftime("%H:%M:%S", time.localtime(op.time))
         if self.options['time'] == 'activity':
             op_time = helper.format_time_reference(op.activity_time)
         if op.concerned_object['name'] is None:
             corpsstr += urllib.parse.unquote( op_time + " : " + op.name + "\n")
         else:
             corpsstr += urllib.parse.unquote( op_time + " : " + op.name + " ( " + op.concerned_object['name'] + " : " + op.concerned_object['id'] + " )\n")
     entete = Gtk.Label(label=entetestr.encode("UTF-8"))
     hb = Gtk.HBox()
     box = Gtk.EventBox()
     tr = TimestampRepresentation(obj_evt.movietime, None, self.controller, 50, 0, None , False)
     if tr is not None:
         hb.pack_start(tr, False, True, 0)
         hb.pack_start(Gtk.VSeparator(), False, False, 0)
     if corpsstr != "":
         hb.set_tooltip_text(corpsstr)
     def box_pressed(w, event, ops):
         if event.button == 1 and event.type == Gdk.EventType._2BUTTON_PRESS:
             #FIXME : need to change details in another way
             self.filters['objects']=[]
             self.filters['objects'].extend(ops)
             self.options['detail']='operations'
             self.DetB.set_label('operations')
             #FIXME color change of the reset button when applying a filter
             self.filter_active(True)
             self.receive(self.tracer.trace)
         return
     box.add(entete)
     box.connect('button-press-event', box_pressed, obj_evt.operations)
     hb.pack_start(box, False, True, 0)
     return hb
Ejemplo n.º 5
0
    def iterator(self):
        """Process input data.

        You can read the output from self.process.stdout or
        self.process.stderr, or any other communication means provided
        by the external application.

        This method should yield dictionaries containing data (see
        GenericImporter for details).
        """
        shot_re = re.compile('Shot log\s+::\s+(.+)')
        exp_re = re.compile('(\d*\.\d*)e\+(\d+)')

        num = 1
        begin = 0
        while True:
            l = self.process.stderr.readline()
            if not l:
                break
            ms = shot_re.findall(l)
            if ms:
                ts = 0
                try:
                    ts = long(ms[0])
                except ValueError:
                    m = exp_re.match(ms[0])
                    if m:
                        ts = long(float(m.group(1)) * 10**int(m.group(2)))
                if ts == 0:
                    continue
                yield {
                    'content': str(num),
                    'begin': begin,
                    # Offset the end timecode by 1 frame.
                    'end': ts - (1000 / config.data.preferences['default-fps'])
                }
                begin = ts
                num += 1
                if self.duration > 0:
                    prg = 1.0 * ts / self.duration
                else:
                    prg = None
                if not self.progress(
                        prg,
                        _("Detected shot #%(num)d at %(pos)s ") % {
                            'num': num,
                            'pos': helper.format_time_reference(ts)
                        }):
                    break
        # Generate last shot
        yield {
            'content': str(num),
            'begin': begin,
            'end': self.duration or (begin + 5000),
        }
Ejemplo n.º 6
0
    def iterator(self):
        """Process input data.

        You can read the output from self.process.stdout or
        self.process.stderr, or any other communication means provided
        by the external application.

        This method should yield dictionaries containing data (see
        GenericImporter for details).
        """
        shot_re=re.compile('Shot log\s+::\s+(.+)')
        exp_re = re.compile('(\d*\.\d*)e\+(\d+)')

        num = 1
        begin = 0
        while True:
            l = self.process.stderr.readline()
            l = l.decode('utf-8')
            if not l:
                break
            logger.debug("Read line %s", l)
            ms = shot_re.findall(l)
            if ms:
                ts = 0
                try:
                    ts = int(ms[0])
                except ValueError:
                    m = exp_re.match(ms[0])
                    if m:
                        ts = int(float(m.group(1)) * 10 ** int(m.group(2)))
                if ts == 0:
                    continue
                logger.debug("Decoded %d timestamp", ts)
                yield {
                    'content': str(num),
                    'begin': begin,
                    'end': ts
                    }
                begin = ts
                num += 1
                if self.duration > 0:
                    prg = 1.0 * ts / self.duration
                else:
                    prg = None
                if not self.progress(prg, _("Detected shot #%(num)d at %(pos)s ") % {
                        'num': num,
                        'pos': helper.format_time_reference(ts)
                        }):
                    break
        # Generate last shot
        yield {
            'content': str(num),
            'begin': begin,
            'end': self.duration or (begin + 5000),
            }
Ejemplo n.º 7
0
 def build_event_box(self, obj_evt):
     # build the widget to present an event :
     # tooltip with event infos
     # image containing snapshot of the event
     # label with the time of the event
     corpsstr = ''
     entetestr = ''
     if obj_evt.content is not None:
         corpsstr = urllib.parse.unquote(obj_evt.content.encode('utf-8'))
     ev_time = time.strftime("%H:%M:%S", time.localtime(obj_evt.time))
     if self.options['time'] == 'activity':
         ev_time = helper.format_time_reference(obj_evt.activity_time)
     if obj_evt.name in self.events_names or obj_evt.name in self.operations_names:
         if ECACatalog.event_names[obj_evt.name]:
             entetestr = "%s : %s" % (ev_time, ECACatalog.event_names[obj_evt.name])
         else:
             entetestr = "%s : %s" % (ev_time, "Event not described")
         if obj_evt.concerned_object['id']:
             entetestr = entetestr + ' (%s)' % obj_evt.concerned_object['id']
     elif obj_evt.name in list(self.incomplete_operations_names.keys()):
         comp = ''
         ob = self.controller.package.get_element_by_id(obj_evt.concerned_object['id'])
         #print "%s %s %s" % (self.controller.package, obj_evt.concerned_object['id'], ob)
         if isinstance(ob, advene.model.annotation.Annotation):
             comp = _('of an annotation (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.annotation.Relation):
             comp = _('of a relation (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.schema.AnnotationType):
             comp = _('of an annotation type (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.schema.RelationType):
             comp = _('of a relation type (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.schema.Schema):
             comp = _('of a schema (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.view.View):
             comp = _('of a view (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.package.Package):
             comp = _('of a package (%s)') % obj_evt.concerned_object['id']
         else:
             comp = _('of an unknown item (%s)') % obj_evt.concerned_object['id']
             #print "%s" % ob
         entetestr = "%s : %s %s" % (ev_time, self.incomplete_operations_names[obj_evt.name], comp)
     else:
         print("unlabelled event : %s" % obj_evt.name)
         entetestr = "%s : %s" % (ev_time, obj_evt.name)
     entete = Gtk.Label(label=entetestr.encode("UTF-8"))
     hb = Gtk.HBox()
     tr = TimestampRepresentation(obj_evt.movietime, None, self.controller, 50, 0, None , False)
     if tr is not None:
         hb.pack_start(tr, False, True, 0)
         hb.pack_start(Gtk.VSeparator(), False, False, 0)
     hb.pack_start(entete, False, True, 0)
     if corpsstr != "":
         hb.set_tooltip_text(corpsstr)
     return hb
Ejemplo n.º 8
0
 def build_event_box(self, obj_evt):
     # build the widget to present an event :
     # tooltip with event infos
     # image containing snapshot of the event
     # label with the time of the event
     corpsstr = ''
     entetestr = ''
     if obj_evt.content is not None:
         corpsstr = urllib.unquote(obj_evt.content.encode('utf-8'))
     ev_time = time.strftime("%H:%M:%S", time.localtime(obj_evt.time))
     if self.options['time'] == 'activity':
         ev_time = helper.format_time_reference(obj_evt.activity_time)
     if obj_evt.name in self.events_names or obj_evt.name in self.operations_names:
         if ECACatalog.event_names[obj_evt.name]:
             entetestr = "%s : %s" % (ev_time, ECACatalog.event_names[obj_evt.name])
         else:
             entetestr = "%s : %s" % (ev_time, "Event not described")
         if obj_evt.concerned_object['id']:
             entetestr = entetestr + ' (%s)' % obj_evt.concerned_object['id']
     elif obj_evt.name in self.incomplete_operations_names.keys():
         comp = ''
         ob = self.controller.package.get_element_by_id(obj_evt.concerned_object['id'])
         #print "%s %s %s" % (self.controller.package, obj_evt.concerned_object['id'], ob)
         if isinstance(ob, advene.model.annotation.Annotation):
             comp = _('of an annotation (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.annotation.Relation):
             comp = _('of a relation (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.schema.AnnotationType):
             comp = _('of an annotation type (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.schema.RelationType):
             comp = _('of a relation type (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.schema.Schema):
             comp = _('of a schema (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.view.View):
             comp = _('of a view (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.package.Package):
             comp = _('of a package (%s)') % obj_evt.concerned_object['id']
         else:
             comp = _('of an unknown item (%s)') % obj_evt.concerned_object['id']
             #print "%s" % ob
         entetestr = "%s : %s %s" % (ev_time, self.incomplete_operations_names[obj_evt.name], comp)
     else:
         print "unlabelled event : %s" % obj_evt.name
         entetestr = "%s : %s" % (ev_time, obj_evt.name)
     entete = gtk.Label(entetestr.encode("UTF-8"))
     hb = gtk.HBox()
     tr = TimestampRepresentation(obj_evt.movietime, self.controller, 50, 0, None , False)
     if tr is not None:
         hb.pack_start(tr, expand=False)
         hb.pack_start(gtk.VSeparator(), expand=False)
     hb.pack_start(entete, expand=False)
     if corpsstr != "":
         hb.set_tooltip_text(corpsstr)
     return hb
Ejemplo n.º 9
0
 def update_last_action_box(self, obj_evt, nav=False):
     if nav:
         tup = Gtk.tooltips_data_get(self.latest['nav_actionBox'])
     else:
         tup = Gtk.tooltips_data_get(self.latest['actionsBox'])
     if tup is None:
         return
     corpsstr = ""
     for op in obj_evt.operations:
         op_time = time.strftime("%H:%M:%S", time.localtime(op.time))
         if self.options['time'] == 'activity':
             op_time = helper.format_time_reference(op.activity_time)
         if op.concerned_object['name'] is None:
             corpsstr += urllib.parse.unquote( op_time + " : " + op.name + "\n")
         else:
             corpsstr += urllib.parse.unquote( op_time + " : " + op.name + " ( " + op.concerned_object['name'] + " : " + op.concerned_object['id'] + " )\n")
     tup[1].set_tooltip_text(corpsstr)
     self.receive(self.tracer.trace)
Ejemplo n.º 10
0
 def update_last_action_box(self, obj_evt, nav=False):
     if nav:
         tup = gtk.tooltips_data_get(self.latest['nav_actionBox'])
     else:
         tup = gtk.tooltips_data_get(self.latest['actionsBox'])
     if tup is None:
         return
     corpsstr = ""
     for op in obj_evt.operations:
         op_time = time.strftime("%H:%M:%S", time.localtime(op.time))
         if self.options['time'] == 'activity':
             op_time = helper.format_time_reference(op.activity_time)
         if op.concerned_object['name'] is None:
             corpsstr += urllib.unquote( op_time + " : " + op.name + "\n")
         else:
             corpsstr += urllib.unquote( op_time + " : " + op.name + " ( " + op.concerned_object['name'] + " : " + op.concerned_object['id'] + " )\n")
     tup[1].set_tooltip_text(corpsstr)
     self.receive(self.tracer.trace)
Ejemplo n.º 11
0
    def export(self, filename):
        RDF = rdflib.RDF
        RDFS = rdflib.RDFS
        XSD = rdflib.XSD

        # Works in source is a package or a type
        package = self.source.ownerPackage

        # Get the namespace from the package metdata
        ontology = package.getMetaData(config.data.namespace, "ontology_uri")
        if not ontology:
            return _(
                "Cannot find the ontology URI. It should be defined as package metadata."
            )
        AO = rdflib.Namespace(ontology)
        #AR = rdflib.Namespace(ontology.replace('/ontology/', '/resource/'))
        AS = rdflib.Namespace("http://www.w3.org/ns/activitystreams#")
        OA = rdflib.Namespace("http://www.w3.org/ns/oa#")

        g = rdflib.Graph()
        g.bind('ao', AO)
        g.bind('oa', OA)
        g.bind('activitystreams', AS)

        collection = BNode()
        page = URIRef("page1")
        g.add((collection, RDF.type, OA.AnnotationCollection))
        g.add((collection, RDFS.label,
               Literal(self.controller.get_title(self.source))))
        g.add((collection, AS.totalItems,
               Literal(len(self.source.annotations),
                       datatype=XSD.nonNegativeInteger)))
        g.add((collection, AS.first, page))

        @lru_cache(maxsize=None)
        def get_user_node(username):
            unode = URIRef(username)
            g.add((unode, RDF.type, OA.Person))
            g.add((unode, OA.nick, Literal(username)))
            return unode

        pageItems = BNode()
        g.add((page, AS.items, pageItems))

        itemcollection = Collection(g, pageItems)

        for a in self.source.annotations:
            anode = URIRef(a.uri)
            itemcollection.append(anode)
            g.add((anode, RDF.type, OA.Annotation))
            g.add((anode, OA.created, Literal(a.date, datatype=XSD.dateTime)))
            g.add((anode, OA.creator, get_user_node(a.author)))

            body = BNode()
            g.add((anode, OA.body, body))

            type_uri = a.type.getMetaData(config.data.namespace,
                                          "ontology_uri")
            if not type_uri:
                logger.warn(_("Cannot determine ontology URI for type %s"),
                            self.controller.get_title(a.type))
                type_uri = a.type.id
            g.add((body, AO.annotationType, URIRef(type_uri)))

            # Build body according to content type
            if a.content.mimetype == 'text/x-advene-keyword-list':
                g.add((body, RDF.type, AO.PredefinedValuesAnnotationType))
                keywords = a.content.parsed()
                keywords_list = list(keywords)

                def add_keyword_to_graph(kw, type_=AO.annotationValue):
                    uri = keywords.get(kw, 'ontology_uri')
                    val = URIRef(uri) if uri else Literal(kw)
                    g.add((body, type_, val))

                prev = None
                while keywords_list:
                    current = keywords_list.pop(0)
                    if current in (TO_KW, VS_KW):
                        if prev is None:
                            logger.error(
                                "Syntax error: %s keyword should have a value before."
                                % current)
                            prev = None
                        elif not keywords_list:
                            logger.error(
                                "Syntax error: %s keyword should have a value after."
                                % current)
                            prev = None
                        else:
                            if current == TO_KW:
                                add_keyword_to_graph(prev,
                                                     AO.fromAnnotationValue)
                                current = keywords_list.pop(0)
                                add_keyword_to_graph(current,
                                                     AO.toAnnotationValue)
                                prev = current  # or None?
                            elif current == VS_KW:
                                # FIXME: how to properly encode contrasting values? Copying TO code for the moment
                                add_keyword_to_graph(prev,
                                                     AO.fromAnnotationValue)
                                current = keywords_list.pop(0)
                                add_keyword_to_graph(current,
                                                     AO.toAnnotationValue)
                                prev = current  # or None?
                            else:
                                logger.error("This should never happen.")
                    else:
                        if prev is not None:
                            add_keyword_to_graph(prev)
                        prev = current
                # Last item
                if prev is not None:
                    add_keyword_to_graph(prev)
            else:
                g.add((body, RDF.type, OA.Text))
                g.add((body, OA.value, Literal(a.content.data)))

            target = BNode()
            g.add((anode, OA.target, target))

            g.add((target, OA.source,
                   URIRef(
                       package.getMetaData(config.data.namespace, "media_uri")
                       or package.mediafile)))

            selector = BNode()
            g.add((target, OA.selector, selector))

            g.add((selector, RDF.type, OA.FragmentSelector))
            g.add((selector, OA.conformsTo,
                   URIRef("http://www.w3.org/TR/media-frags/")))
            g.add((selector, OA.value,
                   Literal("t={},{}".format(
                       helper.format_time_reference(a.fragment.begin),
                       helper.format_time_reference(a.fragment.end)))))

        g.add((page, RDF.type, AS.OrderedCollectionPage))
        g.add((page, AS.items, pageItems))
        g.add((page, AS.startIndex, Literal(0,
                                            datatype=XSD.nonNegativeInteger)))
        g.serialize(destination=filename, format=self.format)
        logger.info(_("Wrote %d triples to %s"), len(g), filename)
        return ""
Ejemplo n.º 12
0
    def validate_and_next(self, new):
        """Validate the current annotation and display the next one.
        """
        i = self.index
        annotation = self.annotations[i]
        batch=object()

        event = Gtk.get_current_event()
        if event.get_state().state & Gdk.ModifierType.CONTROL_MASK:
            # Control-key is held. Split the annotation.
            if new > annotation.fragment.begin and new < annotation.fragment.end:
                self.controller.split_annotation(annotation, new)
                self.message(_("Split annotation #%(current)d into #%(current)d and #%(next)d") % {
                        'current': i + 1,
                        'next': i + 2
                        })
            else:
                self.message(_("Cannot split annotation #%(current)d: out of bounds.") % {
                        'current': i + 1,
                        })
            return True

        if new != annotation.fragment.begin:
            logger.debug("Updating annotation begin from %s to %s", helper.format_time(annotation.fragment.begin), helper.format_time_reference(new))
            self.controller.notify('EditSessionStart', element=annotation, immediate=True)
            annotation.fragment.begin = new
            self.controller.notify('AnnotationEditEnd', annotation=annotation, batch=batch)
            self.controller.notify('EditSessionEnd', element=annotation)
            self.undo_button.set_sensitive(True)

        # Update previous annotation end.
        if i > 0:
            annotation = self.annotations[i - 1]
            if new != annotation.fragment.end:
                self.controller.notify('EditSessionStart', element=annotation, immediate=True)
                annotation.fragment.end = new
                self.controller.notify('AnnotationEditEnd', annotation=annotation, batch=batch)
                self.controller.notify('EditSessionEnd', element=annotation)
            self.message(_("Changed cut between #%(first)d and %(second)d") % { 'first': i + 1,
                                                                                  'second': i + 2 })
        else:
            self.message(_("Changed begin time for first annotation"))
        self.set_index(i + 1)
        return True
Ejemplo n.º 13
0
    def iterator(self, fd):
        progress=0.02
        in_list = False
        start_time = -1
        propname = ''
        data = ''
        for l in fd:
            l=str(l.strip().rstrip(";").strip(), 'latin1')
            if self.model is None:
                if '/modelLDT/' in l:
                    self.model = 'ldt'
                elif '/visu/' in l:
                    self.model = 'visu'

            m=type_re.search(l)
            if m:
                item = { 'type': m.group(1) }
                continue

            if l.startswith(')'):
                # End of list
                item[propname] = data
                in_list = False
                continue

            if in_list:
                data.append(l)
                continue

            m=prop_re.search(l)
            if m:
                propname = m.group(1).lower()
                if propname == 'id':
                    propname = 'id'
                data = m.group(2)
                if data == '(':
                    in_list = True
                    data = []
                    continue

                if num_re.match(data):
                    data = int(data)
                elif data.startswith('"') and data.endswith('"'):
                    data = data.strip('"')

                item[propname] = data

                continue

            if l.startswith('.'):
                self.progress(progress)
                progress += .05

                if start_time == -1:
                    if self.model == 'visu':
                        if item['type'] == 'RecordFilename':
                            start_time = item['begin']
                    else:
                        start_time = item['begin']
                    begin = 0
                    end = default_duration
                else:
                    begin = item['begin'] - start_time
                    #end = item['end'] - start_time
                    end = begin + default_duration

                if item['type'] == 'PresenceStart':
                    self.defaulttype.setMetaData(config.data.namespace_prefix['dc'], 'description', "Trace for %s %s on %s" % (item['surname'], item['name'], time.strftime('%F %H:%M:%S', time.localtime(item['begin'] / 1000))))

                item['_begin'] = helper.format_time_reference(item['begin'])
                item['_end'] = helper.format_time_reference(item['end'])

                yield {
                    'content': "\n".join( "%s=%s" % (k, str(item[k])) for k in sorted(item.keys())).encode('utf8'),
                    'begin': begin,
                    'end' : end,
                    }

        self.progress(1.0)
Ejemplo n.º 14
0
 def build_operation_box(self, obj_evt):
     # build the widget to present an event :
     # tooltip with event infos
     # image containing snapshot of the event
     # label with the time of the event
     corpsstr = ''
     if obj_evt.content is not None:
         corpsstr = urllib.unquote(obj_evt.content.encode('utf-8'))
     ev_time = time.strftime("%H:%M:%S", time.localtime(obj_evt.time))
     if self.options['time'] == 'activity':
         ev_time = helper.format_time_reference(obj_evt.activity_time)
     if obj_evt.name in self.operations_names:
         if ECACatalog.event_names[obj_evt.name]:
             entetestr = "%s : %s" % (ev_time, ECACatalog.event_names[obj_evt.name])
         else:
             entetestr = "%s : %s" % (ev_time, "Operation not described")
         if obj_evt.concerned_object['id']:
             entetestr = entetestr + ' (%s)' % obj_evt.concerned_object['id']
     elif obj_evt.name in self.incomplete_operations_names.keys():
         comp = ''
         # store type of item in the trace
         ob = self.controller.package.get_element_by_id(obj_evt.concerned_object['id'])
         #print "%s %s %s" % (self.controller.package, obj_evt.concerned_object['id'], ob)
         if isinstance(ob, advene.model.annotation.Annotation):
             comp = _('of an annotation (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.annotation.Relation):
             comp = _('of a relation (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.schema.AnnotationType):
             comp = _('of an annotation type (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.schema.RelationType):
             comp = _('of a relation type (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.schema.Schema):
             comp = _('of a schema (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.view.View):
             comp = _('of a view (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.package.Package):
             comp = _('of a package (%s)') % obj_evt.concerned_object['id']
         else:
             comp = _('of an unknown item (%s)') % obj_evt.concerned_object['id']
         entetestr = "%s : %s %s" % (ev_time, self.incomplete_operations_names[obj_evt.name], comp)
     else:
         print "unlabelled event : %s" % obj_evt.name
         entetestr = "%s : %s" % (ev_time, obj_evt.name)
     entete = gtk.Label(entetestr.encode("UTF-8"))
     hb = gtk.HBox()
     box = gtk.EventBox()
     tr = TimestampRepresentation(obj_evt.movietime, self.controller, 50, 0, None , False)
     if tr is not None:
         hb.pack_start(tr, expand=False)
         hb.pack_start(gtk.VSeparator(), expand=False)
     if corpsstr != "":
         box.set_tooltip_text(corpsstr)
     def box_pressed(w, event, id):
         #print "%s %s" % (id, mtime)
         if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS:
             if id is not None:
                 obj = self.controller.package.get_element_by_id(id)
                 if obj is not None:
                     #Need to edit the item
                     #print obj
                     self.controller.gui.edit_element(obj)
                 else:
                     print "item %s no longuer exists" % id
         return
     box.add(entete)
     box.connect('button-press-event', box_pressed, obj_evt.concerned_object['id'])
     hb.pack_start(box, expand=False)
     return hb
Ejemplo n.º 15
0
    def export(self, filename):
        # Works in source is a package or a type
        package = self.source.ownerPackage

        media_uri = package.getMetaData(
            config.data.namespace,
            "media_uri") or self.controller.get_default_media()

        # Get the namespace from the package metdata
        ontology = package.getMetaData(config.data.namespace, "ontology_uri")
        if not ontology:
            return _(
                "Cannot find the ontology URI. It should be defined as package metadata."
            )
        AO = rdflib.Namespace(ontology)
        #AR = rdflib.Namespace(ontology.replace('/ontology/', '/resource/'))
        AS = rdflib.Namespace("http://www.w3.org/ns/activitystreams#")
        OA = rdflib.Namespace("http://www.w3.org/ns/oa#")

        g = rdflib.Graph()
        g.bind('ao', AO)
        g.bind('oa', OA)
        g.bind('activitystreams', AS)
        g.bind('dc', DC)
        g.bind('dcterms', DCTERMS)

        collection = BNode()
        page = URIRef("page1")
        g.add((collection, RDF.type, OA.AnnotationCollection))
        g.add((collection, RDFS.label,
               Literal(self.controller.get_title(self.source))))
        g.add((collection, AS.totalItems,
               Literal(len(self.source.annotations),
                       datatype=XSD.nonNegativeInteger)))
        g.add((collection, AS.first, page))

        pageItems = BNode()
        g.add((page, AS.items, pageItems))

        itemcollection = Collection(g, pageItems)

        def get_annotation_uri(a):
            return "%s/%s" % (media_uri, a.id)

        not_part_of_ontology = set()
        for a in self.source.annotations:
            # First check if it is part of the ontology schema
            type_uri = a.type.getMetaData(config.data.namespace,
                                          "ontology_uri")
            if not type_uri:
                # Report only once by type
                if a.type not in not_part_of_ontology:
                    logger.warning(
                        _("Cannot determine ontology URI for type %s"),
                        self.controller.get_title(a.type))
                    not_part_of_ontology.add(a.type)
                # Just ignore this annotation
                continue
            anode = URIRef(get_annotation_uri(a))
            itemcollection.append(anode)
            g.add((anode, RDF.type, OA.Annotation))
            g.add(
                (anode, DCTERMS.created, Literal(a.date,
                                                 datatype=XSD.dateTime)))
            # We use DC instead of DCTERMS so that we can simply put the string value as a literal
            g.add((anode, DC.creator, Literal(a.author)))

            def new_body(btype=None):
                """Create a new body node
                """
                body = BNode()
                g.add((anode, OA.hasBody, body))

                g.add((body, AO.annotationType, URIRef(type_uri)))
                if btype is not None:
                    g.add((body, RDF.type, btype))
                return body

            value_type_mapping = {
                "evolving": AO.EvolvingValuesAnnotationType,
                "contrasting": AO.ContrastingValuesAnnotationType,
                "predefined": AO.PredefinedValuesAnnotationType
            }
            # Build body according to content type
            if a.type.mimetype == 'text/x-advene-keyword-list':
                keywords = a.content.parsed()

                def get_keyword_uri(kw):
                    uri = keywords.get(kw, 'ontology_uri')
                    val = URIRef(uri) if uri else Literal(kw)
                    return val

                for typedvalues in keywords_to_struct(list(keywords)):
                    if typedvalues is None:
                        logger.warning("Empty typedvalues for %s", keywords)
                        continue
                    body = new_body(value_type_mapping[typedvalues.type])

                    if typedvalues.type == "predefined":
                        for kw in typedvalues.values:
                            g.add((body, AO.annotationValue,
                                   get_keyword_uri(kw)))
                    else:
                        # Generate a sequence for contrasting/evolving values.
                        seq = BNode()
                        Collection(
                            g, seq,
                            [get_keyword_uri(kw) for kw in typedvalues.values])
                        g.add((body, AO.annotationValueSequence, seq))

                # Attach comment to the last body
                if keywords.get_comment():
                    g.add(
                        (body, RDFS.comment, Literal(keywords.get_comment())))

            else:
                body = new_body()
                g.add((body, RDF.type, OA.TextualBody))
                g.add((body, RDF.value, Literal(a.content.data)))

            target = BNode()
            g.add((anode, OA.hasTarget, target))

            g.add((target, OA.hasSource, URIRef(media_uri)))

            selector = BNode()
            g.add((target, OA.hasSelector, selector))

            g.add((selector, RDF.type, OA.FragmentSelector))
            g.add((selector, DCTERMS.conformsTo,
                   URIRef("http://www.w3.org/TR/media-frags/")))
            g.add((selector, RDF.value,
                   Literal("t={},{}".format(
                       helper.format_time_reference(a.fragment.begin),
                       helper.format_time_reference(a.fragment.end)))))

        g.add((page, RDF.type, AS.OrderedCollectionPage))
        g.add((page, AS.items, pageItems))
        g.add((page, AS.startIndex, Literal(0,
                                            datatype=XSD.nonNegativeInteger)))
        if filename is None:
            return g
        else:
            g.serialize(destination=filename, format=self.format)
            logger.info(_("Wrote %(count)d triples to %(filename)s"), {
                "count": len(g),
                "filename": filename
            })
            return ""
Ejemplo n.º 16
0
    def export(self, filename):
        # Works in source is a package or a type
        package = self.source.ownerPackage

        media_uri = package.getMetaData(config.data.namespace, "media_uri") or package.mediafile or package.uri

        # Get the namespace from the package metdata
        ontology = package.getMetaData(config.data.namespace, "ontology_uri")
        if not ontology:
            return _("Cannot find the ontology URI. It should be defined as package metadata.")
        AO = rdflib.Namespace(ontology)
        #AR = rdflib.Namespace(ontology.replace('/ontology/', '/resource/'))
        AS = rdflib.Namespace("http://www.w3.org/ns/activitystreams#")
        OA = rdflib.Namespace("http://www.w3.org/ns/oa#")

        g = rdflib.Graph()
        g.bind('ao', AO)
        g.bind('oa', OA)
        g.bind('activitystreams', AS)
        g.bind('dc', DC)
        g.bind('dcterms', DCTERMS)

        collection = BNode()
        page = URIRef("page1")
        g.add((collection, RDF.type, OA.AnnotationCollection))
        g.add((collection, RDFS.label, Literal(self.controller.get_title(self.source))))
        g.add((collection, AS.totalItems, Literal(len(self.source.annotations), datatype=XSD.nonNegativeInteger)))
        g.add((collection, AS.first, page))

        pageItems = BNode()
        g.add((page, AS.items, pageItems))

        itemcollection = Collection(g, pageItems)

        def get_annotation_uri(a):
            return "%s/%s" % (media_uri, a.id)

        not_part_of_ontology = set()
        for a in self.source.annotations:
            # First check if it is part of the ontology schema
            type_uri = a.type.getMetaData(config.data.namespace, "ontology_uri")
            if not type_uri:
                # Report only once by type
                if a.type not in not_part_of_ontology:
                    logger.warn(_("Cannot determine ontology URI for type %s"), self.controller.get_title(a.type))
                    not_part_of_ontology.add(a.type)
                # Just ignore this annotation
                continue
            anode = URIRef(get_annotation_uri(a))
            itemcollection.append(anode)
            g.add((anode, RDF.type, OA.Annotation))
            g.add((anode, DCTERMS.created, Literal(a.date, datatype=XSD.dateTime)))
            # We use DC instead of DCTERMS so that we can simply put the string value as a literal
            g.add((anode, DC.creator, Literal(a.author)))

            def new_body(btype=None):
                """Create a new body node
                """
                body = BNode()
                g.add((anode, OA.hasBody, body))

                g.add((body, AO.annotationType, URIRef(type_uri)))
                if btype is not None:
                    g.add((body, RDF.type, btype))
                return body

            value_type_mapping = {
                "evolving": AO.EvolvingValuesAnnotationType,
                "contrasting": AO.ContrastingValuesAnnotationType,
                "predefined": AO.PredefinedValuesAnnotationType
            }
            # Build body according to content type
            if a.type.mimetype == 'text/x-advene-keyword-list':
                keywords = a.content.parsed()

                def get_keyword_uri(kw):
                    uri = keywords.get(kw, 'ontology_uri')
                    val = URIRef(uri) if uri else Literal(kw)
                    return val

                for typedvalues in keywords_to_struct(list(keywords)):
                    if typedvalues is None:
                        logger.warn("Empty typedvalues for %s", keywords)
                        continue
                    body = new_body(value_type_mapping[typedvalues.type])

                    if typedvalues.type == "predefined":
                        for kw in typedvalues.values:
                            g.add( (body, AO.annotationValue, get_keyword_uri(kw)) )
                    else:
                        # Generate a sequence for contrasting/evolving values.
                        seq = BNode()
                        Collection(g, seq, [ get_keyword_uri(kw) for kw in typedvalues.values ])
                        g.add( (body, AO.annotationValueSequence, seq) )

                # Attach comment to the last body
                if keywords.get_comment():
                    g.add( (body, RDFS.comment, Literal(keywords.get_comment())) )

            else:
                body = new_body()
                g.add((body, RDF.type, OA.TextualBody))
                g.add((body, RDF.value, Literal(a.content.data)))

            target = BNode()
            g.add((anode, OA.hasTarget, target))

            g.add((target, OA.hasSource, URIRef(media_uri)))

            selector = BNode()
            g.add((target, OA.hasSelector, selector))

            g.add((selector, RDF.type, OA.FragmentSelector))
            g.add((selector, DCTERMS.conformsTo, URIRef("http://www.w3.org/TR/media-frags/")))
            g.add((selector, RDF.value, Literal("t={},{}".format(helper.format_time_reference(a.fragment.begin),
                                                                 helper.format_time_reference(a.fragment.end)))))

        g.add((page, RDF.type, AS.OrderedCollectionPage))
        g.add((page, AS.items, pageItems))
        g.add((page, AS.startIndex, Literal(0, datatype=XSD.nonNegativeInteger)))
        if filename is None:
            return g
        else:
            g.serialize(destination=filename, format=self.format)
            logger.info(_("Wrote %d triples to %s"), len(g), filename)
            return ""
Ejemplo n.º 17
0
    def parse_transcription(self, show_ignored=False, strip_blank=True):
        """Parse the transcription text.

        If show_ignored, then generate a 'ignored' key for ignored
        texts.

        If strip_blank, then strip leading and trailing whitespace and
        newline for each annotation.

        Return : a iterator on a dict with keys
        'begin', 'end', 'content'
        (compatible with advene.util.importer)
        """

        b=self.textview.get_buffer()
        begin=b.get_start_iter()
        end=begin.copy()

        # Special case for the first mark: if the first item in the
        # buffer is a mark, use its time. Else, initialize the time at 0
        a=begin.get_child_anchor()
        if a and a.get_widgets():
            # Found a TextAnchor
            child=a.get_widgets()[0]
            t=child.value
        else:
            t=0

        ignore_next=False
        while end.forward_char():
            a=end.get_child_anchor()
            if a and a.get_widgets():
                # Found a TextAnchor
                child=a.get_widgets()[0]
                timestamp=child.value
                if timestamp < t:
                    # Invalid timestamp mark.
                    self.log(_('Invalid timestamp mark in conversion: %s') % helper.format_time_reference(timestamp))
                    t=timestamp
                    continue
                text=b.get_text(begin, end, include_hidden_chars=False)
                if strip_blank:
                    text=text.rstrip().lstrip()
                if self.empty_re.match(text) and not self.options['empty-annotations']:
                    pass
                elif ignore_next:
                    if show_ignored:
                        yield { 'begin': t,
                                'end':   timestamp,
                                'content': text,
                                'ignored': True }
                else:
                    yield { 'begin': t,
                            'end':   timestamp,
                            'content': text,
                            'ignored': False }
                ignore_next=child.ignore
                t=timestamp
                begin=end.copy()
        # End of buffer. Create the last annotation
        timestamp=self.controller.cached_duration
        text=b.get_text(begin, end, include_hidden_chars=False)
        if self.empty_re.match(text) or ignore_next:
            # Last timestsamp mark
            pass
        else:
            yield { 'begin': t,
                    'end': timestamp,
                    'content': text,
                    'ignored': False }
Ejemplo n.º 18
0
    def iterator(self, fd):
        progress=0.02
        in_list = False
        start_time = -1
        propname = ''
        data = ''
        for l in fd:
            l=unicode(l.strip().rstrip(";").strip(), 'latin1')
            if self.model is None:
                if '/modelLDT/' in l:
                    self.model = 'ldt'
                elif '/visu/' in l:
                    self.model = 'visu'

            m=type_re.search(l)
            if m:
                item = { 'type': m.group(1) }
                continue

            if l.startswith(')'):
                # End of list
                item[propname] = data
                in_list = False
                continue

            if in_list:
                data.append(l)
                continue

            m=prop_re.search(l)
            if m:
                propname = m.group(1).lower()
                if propname == 'id':
                    propname = 'id'
                data = m.group(2)
                if data == '(':
                    in_list = True
                    data = []
                    continue

                if num_re.match(data):
                    data = long(data)
                elif data.startswith('"') and data.endswith('"'):
                    data = data.strip('"')

                item[propname] = data

                continue

            if l.startswith('.'):
                self.progress(progress)
                progress += .05

                if start_time == -1:
                    if self.model == 'visu':
                        if item['type'] == 'RecordFilename':
                            start_time = item['begin']
                    else:
                        start_time = item['begin']
                    begin = 0
                    end = default_duration
                else:
                    begin = item['begin'] - start_time
                    #end = item['end'] - start_time
                    end = begin + default_duration

                if item['type'] == 'PresenceStart':
                    self.defaulttype.setMetaData(config.data.namespace_prefix['dc'], 'description', "Trace for %s %s on %s" % (item['surname'], item['name'], time.strftime('%F %H:%M:%S', time.localtime(item['begin'] / 1000))))

                item['_begin'] = helper.format_time_reference(item['begin'])
                item['_end'] = helper.format_time_reference(item['end'])

                yield {
                    'content': "\n".join( "%s=%s" % (k, str(item[k])) for k in sorted(item.iterkeys())).encode('utf8'),
                    'begin': begin,
                    'end' : end,
                    }

        self.progress(1.0)
Ejemplo n.º 19
0
 def build_operation_box(self, obj_evt):
     # build the widget to present an event :
     # tooltip with event infos
     # image containing snapshot of the event
     # label with the time of the event
     corpsstr = ''
     if obj_evt.content is not None:
         corpsstr = urllib.parse.unquote(obj_evt.content.encode('utf-8'))
     ev_time = time.strftime("%H:%M:%S", time.localtime(obj_evt.time))
     if self.options['time'] == 'activity':
         ev_time = helper.format_time_reference(obj_evt.activity_time)
     if obj_evt.name in self.operations_names:
         if ECACatalog.event_names[obj_evt.name]:
             entetestr = "%s : %s" % (ev_time, ECACatalog.event_names[obj_evt.name])
         else:
             entetestr = "%s : %s" % (ev_time, "Operation not described")
         if obj_evt.concerned_object['id']:
             entetestr = entetestr + ' (%s)' % obj_evt.concerned_object['id']
     elif obj_evt.name in list(self.incomplete_operations_names.keys()):
         comp = ''
         # store type of item in the trace
         ob = self.controller.package.get_element_by_id(obj_evt.concerned_object['id'])
         #print "%s %s %s" % (self.controller.package, obj_evt.concerned_object['id'], ob)
         if isinstance(ob, advene.model.annotation.Annotation):
             comp = _('of an annotation (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.annotation.Relation):
             comp = _('of a relation (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.schema.AnnotationType):
             comp = _('of an annotation type (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.schema.RelationType):
             comp = _('of a relation type (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.schema.Schema):
             comp = _('of a schema (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.view.View):
             comp = _('of a view (%s)') % obj_evt.concerned_object['id']
         elif isinstance(ob,advene.model.package.Package):
             comp = _('of a package (%s)') % obj_evt.concerned_object['id']
         else:
             comp = _('of an unknown item (%s)') % obj_evt.concerned_object['id']
         entetestr = "%s : %s %s" % (ev_time, self.incomplete_operations_names[obj_evt.name], comp)
     else:
         print("unlabelled event : %s" % obj_evt.name)
         entetestr = "%s : %s" % (ev_time, obj_evt.name)
     entete = Gtk.Label(label=entetestr.encode("UTF-8"))
     hb = Gtk.HBox()
     box = Gtk.EventBox()
     tr = TimestampRepresentation(obj_evt.movietime, None, self.controller, 50, 0, None , False)
     if tr is not None:
         hb.pack_start(tr, False, True, 0)
         hb.pack_start(Gtk.VSeparator(), False, False, 0)
     if corpsstr != "":
         box.set_tooltip_text(corpsstr)
     def box_pressed(w, event, id):
         #print "%s %s" % (id, mtime)
         if event.button == 1 and event.type == Gdk.EventType._2BUTTON_PRESS:
             if id is not None:
                 obj = self.controller.package.get_element_by_id(id)
                 if obj is not None:
                     #Need to edit the item
                     #print obj
                     self.controller.gui.edit_element(obj)
                 else:
                     print("item %s no longuer exists" % id)
         return
     box.add(entete)
     box.connect('button-press-event', box_pressed, obj_evt.concerned_object['id'])
     hb.pack_start(box, False, True, 0)
     return hb
Ejemplo n.º 20
0
    def validate_and_next(self, new):
        """Validate the current annotation and display the next one.
        """
        i = self.index
        annotation = self.annotations[i]
        batch = object()

        event = Gtk.get_current_event()
        if event.get_state().state & Gdk.ModifierType.CONTROL_MASK:
            # Control-key is held. Split the annotation.
            if new > annotation.fragment.begin and new < annotation.fragment.end:
                self.controller.split_annotation(annotation, new)
                self.message(
                    _("Split annotation #%(current)d into #%(current)d and #%(next)d"
                      ) % {
                          'current': i + 1,
                          'next': i + 2
                      })
            else:
                self.message(
                    _("Cannot split annotation #%(current)d: out of bounds.") %
                    {
                        'current': i + 1,
                    })
            return True

        if new != annotation.fragment.begin:
            logger.debug("Updating annotation begin from %s to %s",
                         helper.format_time(annotation.fragment.begin),
                         helper.format_time_reference(new))
            self.controller.notify('EditSessionStart',
                                   element=annotation,
                                   immediate=True)
            annotation.fragment.begin = new
            self.controller.notify('AnnotationEditEnd',
                                   annotation=annotation,
                                   batch=batch)
            self.controller.notify('EditSessionEnd', element=annotation)
            self.undo_button.set_sensitive(True)

        # Update previous annotation end.
        if i > 0:
            annotation = self.annotations[i - 1]
            if new != annotation.fragment.end:
                self.controller.notify('EditSessionStart',
                                       element=annotation,
                                       immediate=True)
                annotation.fragment.end = new
                self.controller.notify('AnnotationEditEnd',
                                       annotation=annotation,
                                       batch=batch)
                self.controller.notify('EditSessionEnd', element=annotation)
            self.message(
                _("Changed cut between #%(first)d and %(second)d") % {
                    'first': i + 1,
                    'second': i + 2
                })
        else:
            self.message(_("Changed begin time for first annotation"))
        self.set_index(i + 1)
        return True
Ejemplo n.º 21
0
    def parse_transcription(self, show_ignored=False, strip_blank=True):
        """Parse the transcription text.

        If show_ignored, then generate a 'ignored' key for ignored
        texts.

        If strip_blank, then strip leading and trailing whitespace and
        newline for each annotation.

        Return : a iterator on a dict with keys
        'begin', 'end', 'content'
        (compatible with advene.util.importer)
        """

        b=self.textview.get_buffer()
        begin=b.get_start_iter()
        end=begin.copy()

        # Special case for the first mark: if the first item in the
        # buffer is a mark, use its time. Else, initialize the time at 0
        a=begin.get_child_anchor()
        if a and a.get_widgets():
            # Found a TextAnchor
            child=a.get_widgets()[0]
            t=child.value
        else:
            t=0

        ignore_next=False
        while end.forward_char():
            a=end.get_child_anchor()
            if a and a.get_widgets():
                # Found a TextAnchor
                child=a.get_widgets()[0]
                timestamp=child.value
                if timestamp < t:
                    # Invalid timestamp mark.
                    self.log(_('Invalid timestamp mark in conversion: %s') % helper.format_time_reference(timestamp))
                    t=timestamp
                    continue
                text=b.get_text(begin, end, include_hidden_chars=False)
                if strip_blank:
                    text=text.rstrip().lstrip()
                if self.empty_re.match(text) and not self.options['empty-annotations']:
                    pass
                elif ignore_next:
                    if show_ignored:
                        yield { 'begin': t,
                                'end':   timestamp,
                                'content': text,
                                'ignored': True }
                else:
                    yield { 'begin': t,
                            'end':   timestamp,
                            'content': text,
                            'ignored': False }
                ignore_next=child.ignore
                t=timestamp
                begin=end.copy()
        # End of buffer. Create the last annotation
        timestamp=self.controller.cached_duration
        text=b.get_text(begin, end, include_hidden_chars=False)
        if self.empty_re.match(text) or ignore_next:
            # Last timestsamp mark
            pass
        else:
            yield { 'begin': t,
                    'end': timestamp,
                    'content': text,
                    'ignored': False }