A python example: Parlatype Reference Manual

## A python example

This is a complete working example of how to use PtPlayer with Python:

    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
    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-

    """ parlatype-example.py demonstrates libparlatype.
        Change testfile to an existing file! """

    import gi
    from gi.repository import Parlatype as Pt
    from gi.repository import Gtk
    from gi.repository import GObject  # for GObject.timeout
    gi.require_version('Gtk', '3.0')

    testfile = "file:///home/user/example.mp3"

    def error_message(message, parent):
        msg = Gtk.MessageDialog(parent=parent,
                                flags=Gtk.DialogFlags.MODAL,
                                type=Gtk.MessageType.ERROR,
                                buttons=Gtk.ButtonsType.OK,
                                message_format=message)
        msg.run()
        msg.destroy()

    """ PtPlayer's error signal.
        It's a severe error and the PtPlayer is reset. There is not much we can
        do about it, here we simply quit. """

    def player_error(player, error):
        error_message(error.args[0], win)
        Gtk.main_quit

    """ PtPlayer's end-of-stream signal.
        Player is at the end and changes to paused state. Note that stream means
        any playable source like files, too.
        We set our buttons according to the state. """

    def player_end_of_stream(player):
        button.set_active(False)

    """ The two main functions are Pt.Player.play() and Pt.Player.pause().
        PtWaveviewer scrolls to cursor (follow-cursor) by default but if the user
        has scrolled manually follow-cursor is set to False. Here we assume that on
        play the user wants to follow cursor again. """

    def button_toggled(button):
        if button.get_active():
            viewer.set_property("follow-cursor", True)
            player.play()
        else:
            player.pause()

    """ In this timeout callback we update cursor position and time label. """

    def update_cursor():
        viewer.set_property("playback-cursor", player.get_position())
        text = player.get_current_time_string(Pt.PrecisionType.SECOND_10TH)
        # Sometimes the position can't be retrieved and None is returned.
        if (text):
            label.set_text(text)
        # Continue updating
        return True

    """ PtWaveviewer's cursor-changed signal.
        This means the user clicked on the widget to change cursor position.
        We have to inform the PtPlayer. We set the follow-cursor property, too. """

    def cursor_changed(viewer, position):
        player.jump_to_position(position)
        viewer.set_property("follow-cursor", True)

    """ Player's open async callback.
        Destroy progress dialog and get result. On success get wave data and pass
        it to the PtWaveviewer. Add a timeout of 10 ms to update cursor position
        and time label. """

    def open_callback(player, result):
        progress.destroy()
        try:
            player.open_uri_finish(result)
            # Get data at a resolution of 100 px per second
            data = player.get_data(100)
            viewer.set_wave(data)
            GObject.timeout_add(10, update_cursor)
        except Exception as err:
            error_message(err.args[0], win)

    """ Pass PtPlayer's emitted progress signal to the PtProgressDialog. """

    def progress_update_callback(player, value, dialog):
        dialog.set_progress(value)

    """ PtPlayer's async open function can be cancelled.
        This emits an error message for the open callback. """

    def progress_response_callback(progress, response):
        if response == Gtk.ResponseType.CANCEL:
            player.cancel()

    if testfile == "file:///home/user/example.mp3":
        error_message("Please change 'file:///home/user/example.mp3' in source "
                      "to an existing test file.", None)
        exit()

    # PtPlayer has a failable constructor, if GStreamer can't be initted.
    try:
        player = Pt.Player.new()
    except Exception as err:
        error_message(err.args[0], None)
        exit()

    player.connect("error", player_error)
    player.connect("end-of-stream", player_end_of_stream)
    # For the PtProgressDialog we have to use the async opening function
    player.open_uri_async(testfile, open_callback)

    # Now create the window with play button, PtWaveviewer and time label.
    win = Gtk.Window()
    win.set_border_width(12)
    win.set_default_size(500, 80)
    win.connect("delete-event", Gtk.main_quit)

    viewer = Pt.Waveviewer.new()
    viewer.connect("cursor-changed", cursor_changed)

    button = Gtk.ToggleButton.new_with_label("Play")
    button.connect("toggled", button_toggled)

    label = Gtk.Label("0:00.0")

    hbox = Gtk.Box(spacing=6)
    hbox.pack_start(button, False, False, 0)
    hbox.pack_start(viewer, True, True, 0)
    hbox.pack_start(label, False, False, 0)
    win.add(hbox)
    win.show_all()

    # PtProgressDialog, connect signals and show only, do not progress.run()
    progress = Pt.ProgressDialog.new(win)
    progress.connect("response", progress_response_callback)
    player.connect("load-progress", progress_update_callback, progress)
    progress.show_all()

    Gtk.main()