Skip to content

Commit

Permalink
Add mirror mode
Browse files Browse the repository at this point in the history
  • Loading branch information
hongquan committed Jun 15, 2024
1 parent 3cbbab8 commit 1741f4b
Show file tree
Hide file tree
Showing 13 changed files with 159 additions and 87 deletions.
23 changes: 18 additions & 5 deletions cobang/app.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Copyright © 2020, Nguyễn Hồng Quân <[email protected]>

import os
import io
from gettext import gettext as _
from urllib.parse import urlsplit
Expand All @@ -9,7 +8,6 @@

import gi
import zbar
import logbook
from logbook import Logger
from PIL import Image

Expand All @@ -28,7 +26,7 @@

from gi.repository import GObject, GLib, Gtk, Gdk, Gio, GdkPixbuf, Handy, Rsvg, Gst, GstApp, NM

from .consts import APP_ID, SHORT_NAME
from .consts import APP_ID
from . import __version__
from . import ui
from .resources import get_ui_filepath, guess_content_type, cache_http_file
Expand All @@ -51,6 +49,7 @@ class CoBangApplication(Gtk.Application):
STACK_CHILD_NAME_WEBCAM = 'src_webcam'
STACK_CHILD_NAME_IMAGE = 'src_image'
GST_SOURCE_NAME = 'webcam_source'
GST_FLIP_FILTER_NAME = 'videoflip'
SIGNAL_QRCODE_DETECTED = 'qrcode-detected'
window: Optional[Gtk.Window] = None
main_grid: Optional[Gtk.Grid] = None
Expand All @@ -67,6 +66,7 @@ class CoBangApplication(Gtk.Application):
raw_result_buffer: Optional[Gtk.TextBuffer] = None
webcam_combobox: Optional[Gtk.ComboBox] = None
webcam_store: Optional[Gtk.ListStore] = None
btn_mirror: Optional[Gtk.ToggleButton] = None
frame_image: Optional[Gtk.AspectFrame] = None
# Box holds the emplement to display when no image is chosen
box_image_empty: Optional[Gtk.Box] = None
Expand Down Expand Up @@ -117,7 +117,8 @@ def setup_actions(self):
def build_gstreamer_pipeline(self, src_type: str = 'v4l2src'):
# https://gstreamer.freedesktop.org/documentation/application-development/advanced/pipeline-manipulation.html?gi-language=c#grabbing-data-with-appsink
# Try GL backend first
command = (f'{src_type} name={self.GST_SOURCE_NAME} ! videoconvert ! tee name=t ! '
video_flip_method = 'horizontal-flip' if (self.btn_mirror and self.btn_mirror.get_active()) else 'none'
command = (f'{src_type} name={self.GST_SOURCE_NAME} ! videoflip name={self.GST_FLIP_FILTER_NAME} method={video_flip_method} ! videoconvert ! tee name=t ! '
# FIXME: The produced video screen is wider than expected, with redundant black padding
f'queue ! videoscale ! '
f'glsinkbin sink="gtkglsink name={self.SINK_NAME}" name=sink_bin '
Expand All @@ -132,7 +133,7 @@ def build_gstreamer_pipeline(self, src_type: str = 'v4l2src'):
if not pipeline:
logger.info('OpenGL is not available, fallback to normal GtkSink')
# Fallback to non-GL
command = (f'{src_type} name={self.GST_SOURCE_NAME} ! videoconvert ! tee name=t ! '
command = (f'{src_type} name={self.GST_SOURCE_NAME} ! videoflip name={self.GST_FLIP_FILTER_NAME} method={video_flip_method} ! videoconvert ! tee name=t ! '
f'queue ! videoscale ! gtksink name={self.SINK_NAME} '
't. ! queue leaky=1 max-size-buffers=2 ! video/x-raw,format=GRAY8 ! '
f'appsink name={self.APPSINK_NAME}')
Expand Down Expand Up @@ -167,6 +168,7 @@ def build_main_window(self):
self.raw_result_expander = builder.get_object('raw-result-expander')
self.webcam_store = builder.get_object('webcam-list')
self.webcam_combobox = builder.get_object('webcam-combobox')
self.btn_mirror = builder.get_object('btn-mirror')
self.frame_image = builder.get_object('frame-image')
self.box_image_empty = builder.get_object('box-image-empty')
main_menubutton: Gtk.MenuButton = builder.get_object('main-menubutton')
Expand Down Expand Up @@ -198,6 +200,7 @@ def signal_handlers_for_glade(self):
'on_evbox_playpause_leave_notify_event': self.on_evbox_playpause_leave_notify_event,
'on_info_bar_response': self.on_info_bar_response,
'on_btn_copy_clicked': self.on_btn_copy_clicked,
'on_btn-mirror_toggled': self.on_btn_mirror_toggled,
}

def discover_webcam(self):
Expand Down Expand Up @@ -642,6 +645,16 @@ def on_btn_copy_clicked(self, button: Gtk.Button):
button.set_tooltip_text(_('Copied'))
GLib.timeout_add_seconds(3, remove_tooltip, button)

def on_btn_mirror_toggled(self, button: Gtk.ToggleButton):
if not self.gst_pipeline:
return
ppl_source = self.gst_pipeline.get_by_name(self.GST_SOURCE_NAME)
ppl_source.set_state(Gst.State.NULL)
self.gst_pipeline.set_state(Gst.State.NULL)
mirror = button.get_active()
self.gst_pipeline.get_by_name(self.GST_FLIP_FILTER_NAME).set_property('method', 'horizontal-flip' if mirror else 'none')
self.gst_pipeline.set_state(Gst.State.PLAYING)

def on_info_bar_response(self, infobar: Gtk.InfoBar, response_id: int):
infobar.set_visible(False)

Expand Down
21 changes: 18 additions & 3 deletions data/cobang-resp.glade
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.22"/>
<requires lib="libhandy" version="0.0"/>
Expand Down Expand Up @@ -411,7 +411,22 @@ Remote image (from http://..., sftp://...) is allowed.</property>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkToggleButton" id="btn-mirror">
<property name="label" translatable="yes">Mirror</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="active">True</property>
<signal name="toggled" handler="on_btn-mirror_toggled" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
Expand All @@ -428,7 +443,7 @@ Remote image (from http://..., sftp://...) is allowed.</property>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
<property name="position">2</property>
</packing>
</child>
</object>
Expand Down
5 changes: 5 additions & 0 deletions data/vn.hoabinh.quan.CoBang.appdata.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@
</kudos>

<releases>
<release version="0.14.0" date="2024-06-15" urgency="medium">
<description translate="no">
<p>Add mirror mode.</p>
</description>
</release>
<release version="0.13.1" date="2024-06-08" urgency="medium">
<description translate="no">
<p>Update translation.</p>
Expand Down
2 changes: 1 addition & 1 deletion meson.build
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
project('cobang',
version: '0.13.1',
version: '0.14.0',
meson_version: '>= 0.61',
default_options: [
'warning_level=2',
Expand Down
21 changes: 12 additions & 9 deletions po/cobang.pot
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-03-27 10:09+0700\n"
"POT-Creation-Date: 2024-06-15 17:22+0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
Expand All @@ -17,16 +17,16 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.10.3\n"

#: cobang/app.py:99
#: cobang/app.py:100
msgid "CoBang: QR scanner for Linux"
msgstr ""

#: cobang/app.py:547
#: cobang/app.py:544
#, python-format
msgid "Unsupported file type %s!"
msgstr ""

#: cobang/app.py:648
#: cobang/app.py:645
msgid "Copied"
msgstr ""

Expand Down Expand Up @@ -86,20 +86,24 @@ msgstr ""
msgid "Image"
msgstr ""

#: data/cobang-resp.glade:424
#: data/cobang-resp.glade:419
msgid "Mirror"
msgstr "Gương"

#: data/cobang-resp.glade:439
msgid "Please choose an image file"
msgstr ""

#: data/cobang-resp.glade:472
#: data/cobang-resp.glade:487
msgid "Result"
msgstr ""

#: data/cobang-resp.glade:512
#: data/cobang-resp.glade:527
msgid "Raw result"
msgstr ""

#: data/url-display.glade:16
msgid "Found an URL. Click to open:"
msgid "Found a URL. Click to open:"
msgstr ""

#: data/url-display.glade:26
Expand Down Expand Up @@ -145,4 +149,3 @@ msgstr ""
#: data/wifi-display.glade:101
msgid "Save"
msgstr ""

23 changes: 14 additions & 9 deletions po/de.po
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-03-27 10:09+0700\n"
"POT-Creation-Date: 2024-06-15 17:22+0700\n"
"PO-Revision-Date: 2024-05-26 20:50+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: de\n"
Expand All @@ -16,18 +16,18 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.14.0\n"
"Generated-By: Babel 2.10.3\n"

#: cobang/app.py:99
#: cobang/app.py:100
msgid "CoBang: QR scanner for Linux"
msgstr "CoBang: QR-Scanner für Linux"

#: cobang/app.py:547
#: cobang/app.py:544
#, python-format
msgid "Unsupported file type %s!"
msgstr "Nicht unterstützter Dateityp %s!"

#: cobang/app.py:648
#: cobang/app.py:645
msgid "Copied"
msgstr "Kopiert"

Expand Down Expand Up @@ -94,20 +94,25 @@ msgstr ""
msgid "Image"
msgstr "Bild"

#: data/cobang-resp.glade:424
#: data/cobang-resp.glade:419
msgid "Mirror"
msgstr "Gương"

#: data/cobang-resp.glade:439
msgid "Please choose an image file"
msgstr "Bitte Bild auswählen"

#: data/cobang-resp.glade:472
#: data/cobang-resp.glade:487
msgid "Result"
msgstr "Ergebnis"

#: data/cobang-resp.glade:512
#: data/cobang-resp.glade:527
msgid "Raw result"
msgstr "Unbearbeitetes Ergebnis"

#: data/url-display.glade:16
msgid "Found an URL. Click to open:"
#, fuzzy
msgid "Found a URL. Click to open:"
msgstr "URL gefunden. Zum Öffnen klicken:"

#: data/url-display.glade:26
Expand Down
23 changes: 14 additions & 9 deletions po/fr.po
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: [email protected]\n"
"POT-Creation-Date: 2024-03-27 10:09+0700\n"
"POT-Creation-Date: 2024-06-15 17:22+0700\n"
"PO-Revision-Date: 2023-04-14 19:26+0200\n"
"Last-Translator: Miquel Lionel <[email protected]>\n"
"Language: fr\n"
Expand All @@ -16,19 +16,19 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.14.0\n"
"Generated-By: Babel 2.10.3\n"

#: cobang/app.py:99
#: cobang/app.py:100
#, fuzzy
msgid "CoBang: QR scanner for Linux"
msgstr "Scanneur de code QR pour Linux"

#: cobang/app.py:547
#: cobang/app.py:544
#, python-format
msgid "Unsupported file type %s!"
msgstr "Type de fichier %s non supporté!"

#: cobang/app.py:648
#: cobang/app.py:645
msgid "Copied"
msgstr "Copié"

Expand Down Expand Up @@ -96,20 +96,25 @@ msgstr ""
msgid "Image"
msgstr "Image"

#: data/cobang-resp.glade:424
#: data/cobang-resp.glade:419
msgid "Mirror"
msgstr "Gương"

#: data/cobang-resp.glade:439
msgid "Please choose an image file"
msgstr "Veuillez choisir un fichier image"

#: data/cobang-resp.glade:472
#: data/cobang-resp.glade:487
msgid "Result"
msgstr "Résultat"

#: data/cobang-resp.glade:512
#: data/cobang-resp.glade:527
msgid "Raw result"
msgstr "Résultat brut"

#: data/url-display.glade:16
msgid "Found an URL. Click to open:"
#, fuzzy
msgid "Found a URL. Click to open:"
msgstr "URL trouvée. Cliquez pour ouvrir:"

#: data/url-display.glade:26
Expand Down
Loading

0 comments on commit 1741f4b

Please sign in to comment.