Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PrintCenter

License: MIT

A native, driverless print & scan center for Linux.

PrintCenter works with printers that support IPP Everywhere and eSCL/AirScan — the same standards behind AirPrint and Mopria. In other words: most network printers made in the last decade.

No vendor software. No proprietary drivers. No Wine. No pretending a printer needs a 600 MB "device experience suite" to put ink on paper.

I built this after discovering that my printer supposedly had "no Linux support." Turns out that mostly meant the manufacturer couldn't be bothered to make a Linux application. The printer itself speaks perfectly normal, standardized protocols.

So Linux could already talk to it. What was missing was a decent application.

PrintCenter is my attempt at fixing that: one native PyQt6 application for printing, scanning, printer status, usage statistics, and device information, instead of bouncing between CUPS's web interface, a separate scanning application, and whatever embedded web UI the printer shipped with.

More projects like this are probably on the way, because fuck Windows. I want the hardware I own to work with a normal operating system. Apparently this remains a controversial demand.

"No, here you go" — Claude

Features

  • Print PDFs, images, and documents with the options your printer actually supports. Paper size and type, orientation, color, duplex, quality, scaling, copies, etc. Capabilities are queried directly from the printer rather than being hardcoded into the application.

  • Edit opens the file in an actual editor instead of trying to reinvent one. PDFs go to Okular, images to GIMP, documents to LibreOffice. Save the file and PrintCenter refreshes the preview automatically.

  • Scan directly from the printer's flatbed using eSCL/AirScan. Choose color mode, resolution, and format, preview the result, then save it or throw it straight back into the print flow.

  • Multiple printers are supported. Switch between existing CUPS destinations or add a printer directly by IP address/hostname. The latter is particularly useful on networks where mDNS/Bonjour discovery mysteriously disappears into the void because of client isolation, mesh networking, or other networking "features."

  • Live status without constant useless noise. PrintCenter shows a warning when the printer actually has something to complain about: low ink, paper out, jams, and similar conditions. Otherwise it stays out of the way.

  • Usage statistics track total sheets, color vs. monochrome printing, monthly usage, and recent jobs per printer. Statistics are collected from completed CUPS jobs, including jobs that weren't submitted through PrintCenter.

  • Device Info & Advanced exposes model information, network/signal details, MAC address, maintenance box level, and installed firmware version. It's deliberately kept away from the normal print flow because you probably don't need your printer's MAC address while printing a PDF.

    Firmware updates are intentionally not automated. PrintCenter will show the installed version and take you to the printer's actual update page. Automating firmware flashing for the sake of saving two clicks seemed like an impressively stupid trade.

Requirements

  • Linux with CUPS
  • A printer configured as a CUPS destination
  • Python 3.10+
  • PyQt6, including QtPdf / QtPdfWidgets
  • pycups

Scanning and device information use only Python's standard library. No additional scanning SDK or vendor dependency is required.

Installation

Arch Linux

sudo pacman -S --needed cups python-pyqt6 python-pycups

git clone https://github.com/henriksb/printcenter.git
cd printcenter
./install.sh

install.sh checks the required dependencies and adds PrintCenter to your application menu.

Other distributions

Package names vary slightly because apparently agreeing on names would have been too convenient.

For Debian/Ubuntu:

# Verify the exact PyQt6 package names for your release
sudo apt install cups python3-pyqt6 python3-pyqt6.qtpdf python3-pycups

Fedora:

sudo dnf install cups python3-pyqt6 python3-pycups

If your distribution doesn't package pycups, you can install it with pip instead. Building it requires the CUPS development headers, for example libcups2-dev on Debian/Ubuntu or cups-devel on Fedora.

pip install --user PyQt6 pycups

Then install PrintCenter normally:

git clone https://github.com/henriksb/printcenter.git
cd printcenter
./install.sh

The installer is optional. If you'd rather not install anything:

python3 main.py

That works too.

Printer setup

PrintCenter primarily uses printers already configured in CUPS. It can also add IPP printers through its own Add Printer dialog.

If your printer isn't configured yet, any IPP Everywhere-capable printer can usually be added manually with:

lpadmin -p YourPrinterName -E -v ipp://<printer-ip>/ipp/print -m everywhere

If your printer advertises AirPrint or Mopria support, there's a very good chance this is all you need.

You can also use your desktop environment's normal printer settings if mDNS discovery works properly on your network.

Usage

  1. Start PrintCenter from your application menu or run python3 main.py.
  2. Click Open File…, drag a file into the window, or use Scan… to scan something directly from the printer.
  3. Select whatever print options you want. The available controls come from the capabilities reported by the selected printer.
  4. Click Print.

That's basically it. Printing really shouldn't require more ceremony than this.

Usage Statistics and Device Info & Advanced are available from the toolbar if you want them, and otherwise stay out of your way.

Updates and releases

PrintCenter follows semantic versioning.

The installed version is visible through Check for Updates…, which checks the latest GitHub release. Nothing is downloaded or installed behind your back.

If PrintCenter was cloned from the official repository, it can fast-forward the local checkout after you confirm the update. Other installations are directed to the corresponding GitHub release, where the source archive and Linux binary can be downloaded manually.

Restart PrintCenter after updating.

Every vX.Y.Z Git tag automatically creates a GitHub release containing:

  • the source for that exact version;
  • a Linux x86_64 binary archive;
  • generated release notes.

User-visible changes are documented in CHANGELOG.md, and previous releases remain available through GitHub Releases.

Why would I use this?

Probably because one of these sounds familiar:

  • Your printer supposedly has "no Linux support", despite supporting AirPrint, Mopria, IPP Everywhere, or eSCL. The hardware works fine. The vendor just didn't give you an application.

  • You'd rather have printing, scanning, status, and device information in one place than use CUPS for one thing, a scanning application for another, and the printer's embedded website for everything else.

  • You have multiple network printers and want to switch between them or add another one without digging through system settings.

  • You want to see ink levels and usage statistics without creating an account, installing a vendor application, or sending telemetry into somebody's cloud because apparently printers need accounts now too.

How it works

There are no proprietary printer drivers or vendor SDKs hiding underneath this.

PrintCenter talks to the printer using open protocols wherever possible.

Printing

Printing goes through CUPS using pycups and driverless IPP Everywhere.

Printer capabilities are queried at runtime, so PrintCenter doesn't need a database containing every printer model and whatever arbitrary collection of features its manufacturer decided to expose.

Scanning

Scanning talks directly to the printer's eSCL endpoint over HTTP(S).

The eSCL client is implemented from scratch in scan_backend.py using only Python's urllib and xml.etree. No SANE wrapper, vendor scanning SDK, or external scanning library is required.

Device information

Additional device information is read from the printer's embedded web server.

Unlike IPP and eSCL, this part isn't standardized, so it's intentionally best-effort. See the limitations below.

Project structure

File Purpose
printer_backend.py CUPS/pycups wrapper: capabilities, status, jobs, and printer management
scan_backend.py eSCL/AirScan client, implemented using the standard library
ews_client.py Best-effort parser for the printer's embedded web interface
usage_tracker.py Per-printer SQLite usage history
config.py Persistent configuration and printer selection
constants.py Human-readable mappings for IPP/PWG values
main_window.py, *_dialog.py UI
workers.py Keeps backend/network operations off the GUI thread
main.py Entry point and application-wide styling

Limitations

A project interacting with printers was never going to escape without a limitations section.

No mDNS/Bonjour discovery when adding printers

Printers are added using their IP address or hostname.

This is deliberate.

Some networks use AP/client isolation, mesh configurations, or other setups that block the multicast traffic mDNS relies on while ordinary unicast communication with the printer works perfectly.

Rather than having discovery work most of the time and mysteriously fail the rest, PrintCenter lets you point directly at the printer.

Device information is best-effort

Printing and scanning use standardized protocols.

Device Info does not.

Some additional information is obtained by parsing the printer's embedded web interface, which is obviously more fragile. A manufacturer can change that HTML in a firmware update and suddenly the parser no longer knows where a particular value lives.

For that reason, every field is independent. If PrintCenter can't find something, that field becomes Unavailable instead of taking the entire panel down with it.

Ink levels come from IPP

PrintCenter uses the ink levels reported through IPP.

During development, I found at least one printer where the value exposed through IPP disagreed with the value displayed by the printer's own embedded web page at the exact same time.

I have no idea why.

Rather than display two contradictory answers and make you decide which version of reality your cyan tank occupies, PrintCenter uses the IPP value consistently. It's also the value CUPS itself sees.

Firmware updates are deliberately manual

PrintCenter can display the installed firmware version and link to the printer's official update interface.

It does not flash firmware itself.

A failed print job wastes a sheet of paper. A failed firmware flash can turn a perfectly good printer into an unusually ugly paperweight. Saving a few clicks isn't worth owning that failure mode.

Office documents don't have live previews

PDFs and images can be previewed natively.

Office documents such as .docx and .odt currently cannot. Use Edit to open them in LibreOffice instead.

Hardware testing is still limited

PrintCenter has primarily been developed and tested against an Epson EcoTank ET-2951/ET-2950.

The standards-based parts should work with other printers supporting IPP Everywhere and eSCL, but I obviously do not own every printer ever manufactured.

If yours does something weird, open an issue. If you fix the weird thing, PRs are even better.

License

MIT

Do whatever useful thing you want with it.

Acknowledgments

Built with the help of Claude Code.

Turns out AI is pretty useful when directed toward the noble cause of making printers slightly less shit.

About

Native print & scan center for Linux — driverless IPP Everywhere + eSCL, no vendor drivers needed. Yeah.. it's vibecoded. Sue me (no, don't. please)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages