Skip to content
This repository has been archived by the owner on Mar 9, 2024. It is now read-only.

Commit

Permalink
Fix linting warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
mre committed Mar 16, 2020
1 parent f505701 commit 6e48d48
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 47 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ run: clean ## Run application in shell
test: clean ## Run pytest
poetry run pytest

.PHONY: lint
lint: ## Lint project code
poetry run pylint timelapse

.PHONY: open
open: ## Open project folder in Finder
open .
Expand Down
42 changes: 29 additions & 13 deletions timelapse/__main__.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,42 @@
"""
The main entrypoint of the application,
which initializes the recorder and the encoder.
"""

import os
import time
import subprocess
from pathlib import Path

from AppKit import *
from AppKit import NSObject, NSMenu, NSApplication, NSStatusBar, \
NSMenuItem, NSImage, NSVariableStatusItemLength, objc
from PyObjCTools import AppHelper
from Foundation import NSUserDefaults

from .encoder import Encoder, not_found_msg # Creates timelapse video
from .recorder import Recorder # Takes screenshots
from .notify import * # Shows notifications/alerts
from .encoder import Encoder # Creates timelapse video
from .recorder import Recorder # Takes screenshots
from .notify import notify # Shows notifications/alerts

NOT_FOUND_MSG = """
The ffmpeg command was not found;
ffmpeg is used by this script to make a video file from a set of pngs.
It is typically not installed by default distros , but it is widely available.
On macOS, try running `brew install ffmpeg`.
"""


def dark_mode() -> bool:
"""
Check if the user enabled Dark Mode
"""
return NSUserDefaults.standardUserDefaults().stringForKey_('AppleInterfaceStyle') == "Dark"


# Configuration
start_recording: bool = False # Start recording on launch
encode: bool = True # Create video after recording
screenshot_interval: float = 1.5 # Number of seconds between screenshots
dir_base = str(Path.home()) # Base directory
DIR_BASE = str(Path.home()) # Base directory
dir_app: str = "timelapse" # Output directory
dir_pictures: str = "Pictures" # Place for pictures in filesystem
dir_movies: str = "Movies" # Place for movies in filesystem
Expand Down Expand Up @@ -56,8 +72,8 @@ def applicationDidFinishLaunching_(self, notification) -> None:

# Set correct output paths
self.recorder_output_basedir: str = os.path.join(
dir_base, dir_pictures, dir_app)
self.encoder_output_basedir: str = os.path.join(dir_base, dir_movies)
DIR_BASE, dir_pictures, dir_app)
self.encoder_output_basedir: str = os.path.join(DIR_BASE, dir_movies)

# Create a reference to the statusbar (menubar)
self.statusbar = NSStatusBar.systemStatusBar()
Expand Down Expand Up @@ -85,20 +101,20 @@ def setStatus(self) -> None:
""" Sets the image and menu text according to recording status """
if self.recording:
self.statusitem.setImage_(self.icon_recording)
self.recordButton.setTitle_(text_recorder_running)
self.record_button.setTitle_(text_recorder_running)
self.statusitem.setToolTip_(tooltip_running)
else:
self.statusitem.setImage_(self.icon_idle)
self.recordButton.setTitle_(text_recorder_idle)
self.record_button.setTitle_(text_recorder_idle)
self.statusitem.setToolTip_(tooltip_idle)

def createMenu(self) -> NSMenu:
""" Status bar menu """
menu = NSMenu.alloc().init()
# Bind record event
self.recordButton = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(
self.record_button = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(
text_recorder_idle, 'startStopRecording:', '')
menu.addItem_(self.recordButton)
menu.addItem_(self.record_button)
# Quit event
menuitem = NSMenuItem.alloc().initWithTitle_action_keyEquivalent_(
'Quit', 'terminate:', '')
Expand Down Expand Up @@ -153,7 +169,7 @@ def check_dependencies(self) -> None:
# This is a quick and dirty check; it leaves some spurious output
# for the user to puzzle over.
except OSError:
print(not_found_msg)
print(NOT_FOUND_MSG)

def main():
app = NSApplication.sharedApplication()
Expand All @@ -162,4 +178,4 @@ def main():
AppHelper.runEventLoop()

if __name__ == "__main__":
main()
main()
36 changes: 12 additions & 24 deletions timelapse/encoder.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
"""
Deals with encoding the screenshots to video using ffmpeg.
"""

from threading import Thread # Encoder is a thread
import subprocess
from datetime import datetime
import os
import glob
import fnmatch
import shutil
from .notify import notify # Shows notifications/alerts
from typing import List

not_found_msg = """
The ffmpeg command was not found;
ffmpeg is used by this script to make a video file from a set of pngs.
It is typically not installed by default distros , but it is widely available.
On macOS, try running `brew install ffmpeg`.
"""
from .notify import notify # Shows notifications/alerts


class Encoder(Thread):
Expand Down Expand Up @@ -48,16 +41,11 @@ def run(self) -> None:
"-vf", "format=yuv420p",
"-vcodec", "h264",
self.output]
notify("Timelapse", f"Creating timelapse. This might take a while")
print(' '.join(command))
try:
notify("Timelapse", f"Creating timelapse. This might take a while")
print(' '.join(command))
try:
completed = subprocess.run(
command, capture_output=True, check=True)
except subprocess.CalledProcessError as e:
notify("Timelapse: ffmpeg not found.", e.stderr.decode('utf-8'))
else:
notify("Timelapse", f"Movie saved to `{self.output}`")
except Exception as e:
print("Main exception", e)
notify("Timelapse Error", e)
subprocess.run(command, capture_output=True, check=True)
except subprocess.CalledProcessError as e:
notify("Timelapse: ffmpeg not found.", e.stderr.decode('utf-8'))
else:
notify("Timelapse", f"Movie saved to `{self.output}`")
11 changes: 9 additions & 2 deletions timelapse/notify.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
from subprocess import run
"""
Functionality to show notifications on macOS
"""

import subprocess


def notify(title: str, text: str) -> int:
"""
Show a macOS notification using osascript
"""
script = 'display notification "{}" with title "{}"'.format(text, title)
return run(['osascript', '-e', script]).returncode
return subprocess.run(['osascript', '-e', script], check=True).returncode
23 changes: 15 additions & 8 deletions timelapse/recorder.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
"""
Recorder is responsible for taking regular (1 second) screenshots of the
screen where the mouse is located.
"""

import os
import subprocess # Taking screenshot
import datetime # Filename
from multiprocessing import Process, Event
from PyObjCTools import AppHelper
from AppKit import NSEvent, NSScreen, NSMouseInRect


def get_screen_with_mouse_index() ->int:
mouseLocation = NSEvent.mouseLocation()
"""
Get the ID for the screen where the mouse is currently on.
"""
mouse_location = NSEvent.mouseLocation()
screens = NSScreen.screens()
for i, screen in enumerate(screens):
if NSMouseInRect(mouseLocation, screen.frame(), False):
if NSMouseInRect(mouse_location, screen.frame(), False):
return i
return 0


class Recorder(Process):
"""
Takes a screenshot every 'interval' seconds and saves it into output_dir or a subdirectory thereof.
Takes a screenshot every 'interval' seconds and saves it into output_dir or
a subdirectory thereof.
"""

def __init__(self, output_dir: str, interval: int=4) -> None:
def __init__(self, output_dir: str, interval: int = 4) -> None:
# Initialize the thread
Process.__init__(self)

Expand Down Expand Up @@ -54,6 +60,7 @@ def run(self) -> None:
self._stopped.set()

def get_recording_time(self) ->str:
""" Get the total recording time as a human-readable string """
return str(self.screenshot_counter * self.interval) + " seconds"

def get_filename(self) ->str:
Expand All @@ -67,6 +74,6 @@ def screenshot(self) -> None:
filename: str = self.get_filename()
subprocess.run(
['screencapture', '-S', '-o', '-x', '-D',
str(get_screen_with_mouse_index() + 1), '-t', self.format, filename],
str(get_screen_with_mouse_index() + 1), '-t', self.format, filename],
check=True)
self.screenshot_counter += 1

0 comments on commit 6e48d48

Please sign in to comment.