diff --git a/.github/workflows/pymagewell-linters.yml b/.github/workflows/pymagewell-linters.yml
index 77cd47a..b5a06ae 100644
--- a/.github/workflows/pymagewell-linters.yml
+++ b/.github/workflows/pymagewell-linters.yml
@@ -30,18 +30,18 @@ jobs:
     - name: Lint with flake8
       run: |
         # stop the build if there are Python syntax errors or undefined names
-        flake8 pymagewell --count --select=E9,F63,F7,F82 --show-source --statistics
-        flake8 tests --count --select=E9,F63,F7,F82 --show-source --statistics
+        flake8 src/pymagewell --count --select=E9,F63,F7,F82 --show-source --statistics
+        flake8 src/tests --count --select=E9,F63,F7,F82 --show-source --statistics
         # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
-        flake8 pymagewell --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
-        flake8 tests --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
+        flake8 src/pymagewell --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
+        flake8 src/tests --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
     - name: Cache mypy cache
       uses: AustinScola/mypy-cache-github-action@v1
     - name: Check typing with mypy
       run: |
-        mypy pymagewell
-        mypy tests
+        mypy src/pymagewell
+        mypy src/tests
     - name: Fix formatting with Black
       run: |
-        black --line-length 120 --diff --color --check pymagewell
-        black --line-length 120 --diff --color --check tests
+        black --line-length 120 --diff --color --check src/pymagewell
+        black --line-length 120 --diff --color --check src/tests
diff --git a/MANIFEST.in b/MANIFEST.in
index 3482fee..b2cd746 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,3 +1,6 @@
 include versioneer.py
-include pymagewell/_version.py
-include pymagewell/py.typed
+include src/pymagewell/_version.py
+include src/pymagewell/py.typed
+include src/mwcapture/bin/x64/*.dll
+include src/mwcapture/bin/x86/*.dll
+include src/mwcapture/README.md
\ No newline at end of file
diff --git a/README.md b/README.md
index ff19538..01d3f12 100644
--- a/README.md
+++ b/README.md
@@ -26,28 +26,31 @@ A full working example is provided in
 [`example_script.py`](https://github.com/KCL-BMEIS/pymagewell/blob/main/example_script.py).
 
 First, create a `ProCaptureSettings` dataclass:
+
 ```python
-from pymagewell import (
+from src.pymagewell import (
     ProCaptureSettings, ImageSizeInPixels, TransferMode, ColourFormat
 )
 
 device_settings = ProCaptureSettings(
     dimensions=ImageSizeInPixels(1920, 1080),
     color_format=ColourFormat.BGR24,  # Color format of captured video frames
-    transfer_mode = TransferMode.LOW_LATENCY,
-    num_lines_per_chunk = 64  # has effect only in low latency mode
+    transfer_mode=TransferMode.LOW_LATENCY,
+    num_lines_per_chunk=64  # has effect only in low latency mode
 )
 ```
 Then create a `ProCaptureDevice` (or `MockProCaptureDevice` for testing on a system without a grabber) configured with
 your chosen settings:
+
 ```python
-from pymagewell import ProCaptureDevice
+from src.pymagewell import ProCaptureDevice
 
 device = ProCaptureDevice(settings=device_settings)
 ```
 Then create a `ProCaptureDeviceController` to transfer frames from the device to your PC:
+
 ```python
-from pymagewell import ProCaptureController
+from src.pymagewell import ProCaptureController
 
 controller = ProCaptureController(device)
 ```
diff --git a/linters_and_black.bat b/linters_and_black.bat
index 0687bb3..c8cca32 100644
--- a/linters_and_black.bat
+++ b/linters_and_black.bat
@@ -1,9 +1,9 @@
 echo 'Formatting code with black...'
-black --line-length 120 pymagewell
-black --line-length 120 tests
+black --line-length 120 src/pymagewell
+black --line-length 120 src/tests
 echo 'Running mypy...'
-mypy pymagewell
-mypy tests
+mypy src/pymagewell
+mypy src/tests
 echo 'Running flake8...'
-flake8 pymagewell
-flake8 tests
+flake8 src/pymagewell
+flake8 src/tests
diff --git a/setup.cfg b/setup.cfg
index 9008d42..ff5a0f8 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -7,7 +7,7 @@ url = https://github.com/KCL-BMEIS/pymagewell
 author = Christian Baker
 author_email = christian.baker@kcl.ac.uk,
 license = MIT
-license_file = LICENSE
+license_files = LICENSE
 classifiers =
  Development Status :: 4 - Beta
  Intended Audience :: Developers
@@ -28,15 +28,9 @@ project_urls =
 
 [options]
 zip_safe = False
-packages =
-  pymagewell
-  pymagewell.events
-  pymagewell.events.mock_win32api
-  pymagewell.events.mock_win32event
-  pymagewell.pro_capture_device
-  mwcapture
+packages = find:
 package_dir =
-  =.
+    = src
 include_package_data = True
 install_requires =
  numpy>=1.23.4
@@ -45,8 +39,8 @@ install_requires =
 
 python_requires = >=3.8
 
-[options.package_data]
-* = py.typed
+[options.packages.find]
+where = src
 
 [bdist_wheel]
 universal = false
diff --git a/mwcapture/README.md b/src/mwcapture/README.md
similarity index 100%
rename from mwcapture/README.md
rename to src/mwcapture/README.md
diff --git a/mwcapture/__init__.py b/src/mwcapture/__init__.py
similarity index 100%
rename from mwcapture/__init__.py
rename to src/mwcapture/__init__.py
diff --git a/mwcapture/bin/x64/LibMWCapture.dll b/src/mwcapture/bin/x64/LibMWCapture.dll
similarity index 100%
rename from mwcapture/bin/x64/LibMWCapture.dll
rename to src/mwcapture/bin/x64/LibMWCapture.dll
diff --git a/mwcapture/bin/x64/avcodec-57.dll b/src/mwcapture/bin/x64/avcodec-57.dll
similarity index 100%
rename from mwcapture/bin/x64/avcodec-57.dll
rename to src/mwcapture/bin/x64/avcodec-57.dll
diff --git a/mwcapture/bin/x64/avformat-57.dll b/src/mwcapture/bin/x64/avformat-57.dll
similarity index 100%
rename from mwcapture/bin/x64/avformat-57.dll
rename to src/mwcapture/bin/x64/avformat-57.dll
diff --git a/mwcapture/bin/x64/avutil-55.dll b/src/mwcapture/bin/x64/avutil-55.dll
similarity index 100%
rename from mwcapture/bin/x64/avutil-55.dll
rename to src/mwcapture/bin/x64/avutil-55.dll
diff --git a/mwcapture/bin/x64/mw_av_encoder.dll b/src/mwcapture/bin/x64/mw_av_encoder.dll
similarity index 100%
rename from mwcapture/bin/x64/mw_av_encoder.dll
rename to src/mwcapture/bin/x64/mw_av_encoder.dll
diff --git a/mwcapture/bin/x64/mw_av_encoderd.dll b/src/mwcapture/bin/x64/mw_av_encoderd.dll
similarity index 100%
rename from mwcapture/bin/x64/mw_av_encoderd.dll
rename to src/mwcapture/bin/x64/mw_av_encoderd.dll
diff --git a/mwcapture/bin/x64/mw_mp4.dll b/src/mwcapture/bin/x64/mw_mp4.dll
similarity index 100%
rename from mwcapture/bin/x64/mw_mp4.dll
rename to src/mwcapture/bin/x64/mw_mp4.dll
diff --git a/mwcapture/bin/x64/swresample-2.dll b/src/mwcapture/bin/x64/swresample-2.dll
similarity index 100%
rename from mwcapture/bin/x64/swresample-2.dll
rename to src/mwcapture/bin/x64/swresample-2.dll
diff --git a/mwcapture/bin/x86/LibMWCapture.dll b/src/mwcapture/bin/x86/LibMWCapture.dll
similarity index 100%
rename from mwcapture/bin/x86/LibMWCapture.dll
rename to src/mwcapture/bin/x86/LibMWCapture.dll
diff --git a/mwcapture/bin/x86/avcodec-57.dll b/src/mwcapture/bin/x86/avcodec-57.dll
similarity index 100%
rename from mwcapture/bin/x86/avcodec-57.dll
rename to src/mwcapture/bin/x86/avcodec-57.dll
diff --git a/mwcapture/bin/x86/avformat-57.dll b/src/mwcapture/bin/x86/avformat-57.dll
similarity index 100%
rename from mwcapture/bin/x86/avformat-57.dll
rename to src/mwcapture/bin/x86/avformat-57.dll
diff --git a/mwcapture/bin/x86/avutil-55.dll b/src/mwcapture/bin/x86/avutil-55.dll
similarity index 100%
rename from mwcapture/bin/x86/avutil-55.dll
rename to src/mwcapture/bin/x86/avutil-55.dll
diff --git a/mwcapture/bin/x86/mw_av_encoder.dll b/src/mwcapture/bin/x86/mw_av_encoder.dll
similarity index 100%
rename from mwcapture/bin/x86/mw_av_encoder.dll
rename to src/mwcapture/bin/x86/mw_av_encoder.dll
diff --git a/mwcapture/bin/x86/mw_av_encoderd.dll b/src/mwcapture/bin/x86/mw_av_encoderd.dll
similarity index 100%
rename from mwcapture/bin/x86/mw_av_encoderd.dll
rename to src/mwcapture/bin/x86/mw_av_encoderd.dll
diff --git a/mwcapture/bin/x86/mw_mp4.dll b/src/mwcapture/bin/x86/mw_mp4.dll
similarity index 100%
rename from mwcapture/bin/x86/mw_mp4.dll
rename to src/mwcapture/bin/x86/mw_mp4.dll
diff --git a/mwcapture/bin/x86/swresample-2.dll b/src/mwcapture/bin/x86/swresample-2.dll
similarity index 100%
rename from mwcapture/bin/x86/swresample-2.dll
rename to src/mwcapture/bin/x86/swresample-2.dll
diff --git a/mwcapture/libmwcapture.py b/src/mwcapture/libmwcapture.py
similarity index 100%
rename from mwcapture/libmwcapture.py
rename to src/mwcapture/libmwcapture.py
diff --git a/pymagewell/__init__.py b/src/pymagewell/__init__.py
similarity index 100%
rename from pymagewell/__init__.py
rename to src/pymagewell/__init__.py
diff --git a/pymagewell/_version.py b/src/pymagewell/_version.py
similarity index 100%
rename from pymagewell/_version.py
rename to src/pymagewell/_version.py
diff --git a/pymagewell/events/__init__.py b/src/pymagewell/events/__init__.py
similarity index 100%
rename from pymagewell/events/__init__.py
rename to src/pymagewell/events/__init__.py
diff --git a/pymagewell/events/device_events.py b/src/pymagewell/events/device_events.py
similarity index 100%
rename from pymagewell/events/device_events.py
rename to src/pymagewell/events/device_events.py
diff --git a/pymagewell/events/event_base.py b/src/pymagewell/events/event_base.py
similarity index 100%
rename from pymagewell/events/event_base.py
rename to src/pymagewell/events/event_base.py
diff --git a/pymagewell/events/mock_win32api/__init__.py b/src/pymagewell/events/mock_win32api/__init__.py
similarity index 100%
rename from pymagewell/events/mock_win32api/__init__.py
rename to src/pymagewell/events/mock_win32api/__init__.py
diff --git a/pymagewell/events/mock_win32event/__init__.py b/src/pymagewell/events/mock_win32event/__init__.py
similarity index 100%
rename from pymagewell/events/mock_win32event/__init__.py
rename to src/pymagewell/events/mock_win32event/__init__.py
diff --git a/pymagewell/events/notification.py b/src/pymagewell/events/notification.py
similarity index 100%
rename from pymagewell/events/notification.py
rename to src/pymagewell/events/notification.py
diff --git a/pymagewell/exceptions.py b/src/pymagewell/exceptions.py
similarity index 100%
rename from pymagewell/exceptions.py
rename to src/pymagewell/exceptions.py
diff --git a/pymagewell/pro_capture_controller.py b/src/pymagewell/pro_capture_controller.py
similarity index 100%
rename from pymagewell/pro_capture_controller.py
rename to src/pymagewell/pro_capture_controller.py
diff --git a/pymagewell/pro_capture_device/__init__.py b/src/pymagewell/pro_capture_device/__init__.py
similarity index 100%
rename from pymagewell/pro_capture_device/__init__.py
rename to src/pymagewell/pro_capture_device/__init__.py
diff --git a/pymagewell/pro_capture_device/device_interface.py b/src/pymagewell/pro_capture_device/device_interface.py
similarity index 100%
rename from pymagewell/pro_capture_device/device_interface.py
rename to src/pymagewell/pro_capture_device/device_interface.py
diff --git a/pymagewell/pro_capture_device/device_settings.py b/src/pymagewell/pro_capture_device/device_settings.py
similarity index 100%
rename from pymagewell/pro_capture_device/device_settings.py
rename to src/pymagewell/pro_capture_device/device_settings.py
diff --git a/pymagewell/pro_capture_device/device_status.py b/src/pymagewell/pro_capture_device/device_status.py
similarity index 100%
rename from pymagewell/pro_capture_device/device_status.py
rename to src/pymagewell/pro_capture_device/device_status.py
diff --git a/pymagewell/pro_capture_device/mock_pro_capture_device.py b/src/pymagewell/pro_capture_device/mock_pro_capture_device.py
similarity index 99%
rename from pymagewell/pro_capture_device/mock_pro_capture_device.py
rename to src/pymagewell/pro_capture_device/mock_pro_capture_device.py
index 5417250..c2f6e8b 100644
--- a/pymagewell/pro_capture_device/mock_pro_capture_device.py
+++ b/src/pymagewell/pro_capture_device/mock_pro_capture_device.py
@@ -50,7 +50,7 @@
 
 class MockProCaptureDevice(ProCaptureDeviceImpl):
     """MockProCaptureDevice is intended to be used during testing, development and CI in the absence of a hardware frame
-    grabber or Magwell Windows SDK. Does not require Magewell driver or hardware.
+    grabber or Magewell Windows SDK. Does not require Magewell driver or hardware.
 
     Only TransferMode.Timer is supported.
 
diff --git a/pymagewell/pro_capture_device/pro_capture_device.py b/src/pymagewell/pro_capture_device/pro_capture_device.py
similarity index 100%
rename from pymagewell/pro_capture_device/pro_capture_device.py
rename to src/pymagewell/pro_capture_device/pro_capture_device.py
diff --git a/pymagewell/pro_capture_device/pro_capture_device_impl.py b/src/pymagewell/pro_capture_device/pro_capture_device_impl.py
similarity index 100%
rename from pymagewell/pro_capture_device/pro_capture_device_impl.py
rename to src/pymagewell/pro_capture_device/pro_capture_device_impl.py
diff --git a/pymagewell/py.typed b/src/pymagewell/py.typed
similarity index 100%
rename from pymagewell/py.typed
rename to src/pymagewell/py.typed
diff --git a/pymagewell/video_frame.py b/src/pymagewell/video_frame.py
similarity index 100%
rename from pymagewell/video_frame.py
rename to src/pymagewell/video_frame.py
diff --git a/tests/__init__.py b/src/tests/__init__.py
similarity index 100%
rename from tests/__init__.py
rename to src/tests/__init__.py
diff --git a/tests/conftest.py b/src/tests/conftest.py
similarity index 100%
rename from tests/conftest.py
rename to src/tests/conftest.py
diff --git a/tests/test_capture_controller.py b/src/tests/test_capture_controller.py
similarity index 100%
rename from tests/test_capture_controller.py
rename to src/tests/test_capture_controller.py
diff --git a/tests/test_device.py b/src/tests/test_device.py
similarity index 100%
rename from tests/test_device.py
rename to src/tests/test_device.py
diff --git a/tests/test_event.py b/src/tests/test_event.py
similarity index 100%
rename from tests/test_event.py
rename to src/tests/test_event.py