Daniel Brötzmann pushed to branch master at gajim / gajim
Commits:
-
33cbaadc
by wurstsalat at 2021-12-18T22:56:55+01:00
-
6b58d0d0
by wurstsalat at 2021-12-19T00:22:06+01:00
4 changed files:
- gajim/common/multimedia_helpers.py
- gajim/common/preview.py
- gajim/data/gui/preview.ui
- gajim/gtk/preview.py
Changes:
| ... | ... | @@ -14,6 +14,10 @@ |
| 14 | 14 |
# You should have received a copy of the GNU General Public License
|
| 15 | 15 |
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
| 16 | 16 |
|
| 17 |
+from __future__ import annotations
|
|
| 18 |
+from typing import Dict
|
|
| 19 |
+from typing import Optional
|
|
| 20 |
+ |
|
| 17 | 21 |
import logging
|
| 18 | 22 |
|
| 19 | 23 |
try:
|
| ... | ... | @@ -27,23 +31,25 @@ |
| 27 | 31 |
|
| 28 | 32 |
|
| 29 | 33 |
class DeviceManager:
|
| 30 |
- def __init__(self):
|
|
| 31 |
- self.devices = {}
|
|
| 34 |
+ def __init__(self) -> None:
|
|
| 35 |
+ self.devices: Dict[str, str] = {}
|
|
| 32 | 36 |
|
| 33 |
- def detect(self):
|
|
| 37 |
+ def detect(self) -> None:
|
|
| 34 | 38 |
self.devices = {}
|
| 35 | 39 |
|
| 36 |
- def get_devices(self):
|
|
| 40 |
+ def get_devices(self) -> Dict[str, str]:
|
|
| 37 | 41 |
if not self.devices:
|
| 38 | 42 |
self.detect()
|
| 39 | 43 |
return self.devices
|
| 40 | 44 |
|
| 41 |
- def detect_element(self, name, text, pipe='%s'):
|
|
| 45 |
+ def detect_element(self, name: str, text: str, pipe: str = '%s') -> None:
|
|
| 42 | 46 |
if Gst.ElementFactory.find(name):
|
| 43 |
- element = Gst.ElementFactory.make(name, '%spresencetest' % name)
|
|
| 47 |
+ element: Optional[Gst.Element] = Gst.ElementFactory.make(
|
|
| 48 |
+ name, f'{name}presencetest')
|
|
| 44 | 49 |
if element is None:
|
| 45 | 50 |
log.warning('could not create %spresencetest', name)
|
| 46 | 51 |
return
|
| 52 |
+ |
|
| 47 | 53 |
if hasattr(element.props, 'device'):
|
| 48 | 54 |
element.set_state(Gst.State.READY)
|
| 49 | 55 |
devices = element.get_properties('device')
|
| ... | ... | @@ -57,7 +63,7 @@ def detect_element(self, name, text, pipe='%s'): |
| 57 | 63 |
element.set_state(Gst.State.READY)
|
| 58 | 64 |
device_name = element.get_property('device-name')
|
| 59 | 65 |
self.devices[text % device_name] = pipe % \
|
| 60 |
- '%s device=%s' % (name, device)
|
|
| 66 |
+ f'{name} device={device}'
|
|
| 61 | 67 |
element.set_state(Gst.State.NULL)
|
| 62 | 68 |
else:
|
| 63 | 69 |
self.devices[text] = pipe % name
|
| ... | ... | @@ -66,8 +72,8 @@ def detect_element(self, name, text, pipe='%s'): |
| 66 | 72 |
|
| 67 | 73 |
|
| 68 | 74 |
class AudioInputManager(DeviceManager):
|
| 69 |
- def detect(self):
|
|
| 70 |
- self.devices = {}
|
|
| 75 |
+ def detect(self) -> None:
|
|
| 76 |
+ self.devices: Dict[str, str] = {}
|
|
| 71 | 77 |
# Test src
|
| 72 | 78 |
self.detect_element('audiotestsrc', _('Audio test'),
|
| 73 | 79 |
'%s is-live=true name=gajim_vol')
|
| ... | ... | @@ -83,8 +89,8 @@ def detect(self): |
| 83 | 89 |
|
| 84 | 90 |
|
| 85 | 91 |
class AudioOutputManager(DeviceManager):
|
| 86 |
- def detect(self):
|
|
| 87 |
- self.devices = {}
|
|
| 92 |
+ def detect(self) -> None:
|
|
| 93 |
+ self.devices: Dict[str, str] = {}
|
|
| 88 | 94 |
# Fake sink
|
| 89 | 95 |
self.detect_element('fakesink', _('Fake audio output'))
|
| 90 | 96 |
# Auto sink
|
| ... | ... | @@ -96,8 +102,8 @@ def detect(self): |
| 96 | 102 |
|
| 97 | 103 |
|
| 98 | 104 |
class VideoInputManager(DeviceManager):
|
| 99 |
- def detect(self):
|
|
| 100 |
- self.devices = {}
|
|
| 105 |
+ def detect(self) -> None:
|
|
| 106 |
+ self.devices: Dict[str, str] = {}
|
|
| 101 | 107 |
# Test src
|
| 102 | 108 |
self.detect_element('videotestsrc', _('Video test'),
|
| 103 | 109 |
'%s is-live=true ! video/x-raw,framerate=10/1 ! videoconvert')
|
| ... | ... | @@ -78,6 +78,7 @@ def __init__(self, |
| 78 | 78 |
self.thumbnail: Optional[bytes] = None
|
| 79 | 79 |
self.mime_type: str = ''
|
| 80 | 80 |
self.file_size: int = 0
|
| 81 |
+ self._received_size: int = 0
|
|
| 81 | 82 |
|
| 82 | 83 |
self.key: Optional[bytes] = None
|
| 83 | 84 |
self.iv: Optional[bytes] = None
|
| ... | ... | @@ -149,6 +150,14 @@ def create_thumbnail(self, data: bytes) -> bool: |
| 149 | 150 |
def update_widget(self, data: Optional[GdkPixbufType] = None) -> None:
|
| 150 | 151 |
self._widget.update(self, data)
|
| 151 | 152 |
|
| 153 |
+ def update_progress(self, size: int) -> None:
|
|
| 154 |
+ self._received_size += size
|
|
| 155 |
+ if self.file_size == 0 or self._received_size == 0:
|
|
| 156 |
+ return
|
|
| 157 |
+ |
|
| 158 |
+ progress = self._received_size / self.file_size
|
|
| 159 |
+ self._widget.update_progress(self, progress)
|
|
| 160 |
+ |
|
| 152 | 161 |
|
| 153 | 162 |
class PreviewManager:
|
| 154 | 163 |
def __init__(self) -> None:
|
| ... | ... | @@ -361,6 +370,7 @@ def download_content(self, |
| 361 | 370 |
message.connect('starting', self._check_certificate, preview)
|
| 362 | 371 |
message.connect(
|
| 363 | 372 |
'content-sniffed', self._on_content_sniffed, preview, force)
|
| 373 |
+ message.connect('got-chunk', self._on_got_chunk, preview)
|
|
| 364 | 374 |
|
| 365 | 375 |
session = self._get_session(preview.account)
|
| 366 | 376 |
session.queue_message(message, self._on_finished, preview)
|
| ... | ... | @@ -407,6 +417,13 @@ def _on_content_sniffed(self, |
| 407 | 417 |
|
| 408 | 418 |
preview.update_widget()
|
| 409 | 419 |
|
| 420 |
+ def _on_got_chunk(self,
|
|
| 421 |
+ _message: Soup.Message,
|
|
| 422 |
+ chunk: Soup.Buffer,
|
|
| 423 |
+ preview: Preview
|
|
| 424 |
+ ) -> None:
|
|
| 425 |
+ preview.update_progress(len(chunk.get_data()))
|
|
| 426 |
+ |
|
| 410 | 427 |
def _on_finished(self,
|
| 411 | 428 |
_session: Soup.Session,
|
| 412 | 429 |
message: Soup.Message,
|
| ... | ... | @@ -42,6 +42,47 @@ |
| 42 | 42 |
<property name="can-focus">False</property>
|
| 43 | 43 |
<property name="orientation">vertical</property>
|
| 44 | 44 |
<property name="spacing">3</property>
|
| 45 |
+ <child>
|
|
| 46 |
+ <object class="GtkEventBox" id="image_event_box">
|
|
| 47 |
+ <property name="visible">True</property>
|
|
| 48 |
+ <property name="can-focus">False</property>
|
|
| 49 |
+ <property name="halign">center</property>
|
|
| 50 |
+ <signal name="realize" handler="_on_realize" swapped="no"/>
|
|
| 51 |
+ <child>
|
|
| 52 |
+ <object class="GtkButton" id="image_button">
|
|
| 53 |
+ <property name="visible">True</property>
|
|
| 54 |
+ <property name="can-focus">True</property>
|
|
| 55 |
+ <property name="receives-default">False</property>
|
|
| 56 |
+ <property name="relief">none</property>
|
|
| 57 |
+ <signal name="button-press-event" handler="_on_button_press_event" swapped="no"/>
|
|
| 58 |
+ <signal name="clicked" handler="_on_content_button_clicked" swapped="no"/>
|
|
| 59 |
+ <child>
|
|
| 60 |
+ <placeholder/>
|
|
| 61 |
+ </child>
|
|
| 62 |
+ <style>
|
|
| 63 |
+ <class name="preview-image-button"/>
|
|
| 64 |
+ </style>
|
|
| 65 |
+ </object>
|
|
| 66 |
+ </child>
|
|
| 67 |
+ </object>
|
|
| 68 |
+ <packing>
|
|
| 69 |
+ <property name="expand">False</property>
|
|
| 70 |
+ <property name="fill">True</property>
|
|
| 71 |
+ <property name="position">0</property>
|
|
| 72 |
+ </packing>
|
|
| 73 |
+ </child>
|
|
| 74 |
+ <child>
|
|
| 75 |
+ <object class="GtkProgressBar" id="progressbar">
|
|
| 76 |
+ <property name="can-focus">False</property>
|
|
| 77 |
+ <property name="no-show-all">True</property>
|
|
| 78 |
+ <property name="show-text">True</property>
|
|
| 79 |
+ </object>
|
|
| 80 |
+ <packing>
|
|
| 81 |
+ <property name="expand">False</property>
|
|
| 82 |
+ <property name="fill">True</property>
|
|
| 83 |
+ <property name="position">1</property>
|
|
| 84 |
+ </packing>
|
|
| 85 |
+ </child>
|
|
| 45 | 86 |
<child>
|
| 46 | 87 |
<object class="GtkBox" id="button_box">
|
| 47 | 88 |
<property name="visible">True</property>
|
| ... | ... | @@ -207,36 +248,7 @@ |
| 207 | 248 |
<property name="expand">False</property>
|
| 208 | 249 |
<property name="fill">True</property>
|
| 209 | 250 |
<property name="pack-type">end</property>
|
| 210 |
- <property name="position">0</property>
|
|
| 211 |
- </packing>
|
|
| 212 |
- </child>
|
|
| 213 |
- <child>
|
|
| 214 |
- <object class="GtkEventBox" id="image_event_box">
|
|
| 215 |
- <property name="visible">True</property>
|
|
| 216 |
- <property name="can-focus">False</property>
|
|
| 217 |
- <property name="halign">center</property>
|
|
| 218 |
- <signal name="realize" handler="_on_realize" swapped="no"/>
|
|
| 219 |
- <child>
|
|
| 220 |
- <object class="GtkButton" id="image_button">
|
|
| 221 |
- <property name="visible">True</property>
|
|
| 222 |
- <property name="can-focus">True</property>
|
|
| 223 |
- <property name="receives-default">False</property>
|
|
| 224 |
- <property name="relief">none</property>
|
|
| 225 |
- <signal name="button-press-event" handler="_on_button_press_event" swapped="no"/>
|
|
| 226 |
- <signal name="clicked" handler="_on_content_button_clicked" swapped="no"/>
|
|
| 227 |
- <child>
|
|
| 228 |
- <placeholder/>
|
|
| 229 |
- </child>
|
|
| 230 |
- <style>
|
|
| 231 |
- <class name="preview-image-button"/>
|
|
| 232 |
- </style>
|
|
| 233 |
- </object>
|
|
| 234 |
- </child>
|
|
| 235 |
- </object>
|
|
| 236 |
- <packing>
|
|
| 237 |
- <property name="expand">False</property>
|
|
| 238 |
- <property name="fill">True</property>
|
|
| 239 |
- <property name="position">1</property>
|
|
| 251 |
+ <property name="position">2</property>
|
|
| 240 | 252 |
</packing>
|
| 241 | 253 |
</child>
|
| 242 | 254 |
</object>
|
| ... | ... | @@ -66,8 +66,13 @@ def get_text(self) -> str: |
| 66 | 66 |
return ''
|
| 67 | 67 |
return self._preview.uri
|
| 68 | 68 |
|
| 69 |
+ def update_progress(self, _preview: Preview, progress: float) -> None:
|
|
| 70 |
+ self._ui.progressbar.show()
|
|
| 71 |
+ self._ui.progressbar.set_fraction(progress)
|
|
| 72 |
+ |
|
| 69 | 73 |
def update(self, preview: Preview, data: Optional[GdkPixbufType]) -> None:
|
| 70 | 74 |
self._preview = preview
|
| 75 |
+ self._ui.progressbar.hide()
|
|
| 71 | 76 |
|
| 72 | 77 |
if preview.is_geo_uri:
|
| 73 | 78 |
data = load_icon('map',
|