From 87f0c75967f90883506f15d03b29f0d67fb69883 Mon Sep 17 00:00:00 2001 From: Michael Pfeiffer Date: Tue, 26 Nov 2002 23:32:04 +0000 Subject: [PATCH] Clean up. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2094 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/print/BeUtils.h | 101 ------- src/servers/print/ConfigWindow.cpp | 117 +++++++- src/servers/print/ConfigWindow.h | 4 +- src/servers/print/Jamfile | 12 +- src/servers/print/PrintServerApp.R5.cpp | 35 +++ .../print/PrintServerApp.Scripting.cpp | 2 +- src/servers/print/PrintServerApp.cpp | 79 ++++-- src/servers/print/PrintServerApp.h | 13 +- src/servers/print/Printer.Scripting.cpp | 2 +- src/servers/print/Printer.cpp | 27 +- src/servers/print/Printer.h | 16 +- src/servers/print/{ => shared}/BeUtils.cpp | 2 +- src/servers/print/shared/FolderWatcher.cpp | 175 ++++++++++++ src/servers/print/shared/Jamfile | 11 + src/servers/print/shared/Jobs.cpp | 265 ++++++++++++++++++ 15 files changed, 706 insertions(+), 155 deletions(-) delete mode 100644 src/servers/print/BeUtils.h rename src/servers/print/{ => shared}/BeUtils.cpp (98%) create mode 100644 src/servers/print/shared/FolderWatcher.cpp create mode 100644 src/servers/print/shared/Jamfile create mode 100644 src/servers/print/shared/Jobs.cpp diff --git a/src/servers/print/BeUtils.h b/src/servers/print/BeUtils.h deleted file mode 100644 index 6aee43a00f..0000000000 --- a/src/servers/print/BeUtils.h +++ /dev/null @@ -1,101 +0,0 @@ -/*****************************************************************************/ -// BeUtils.cpp -// -// Version: 1.0.0d1 -// -// Several utilities for writing applications for the BeOS. It are small -// very specific functions, but generally useful (could be here because of a -// lack in the APIs, or just sheer lazyness :)) -// -// Authors -// Ithamar R. Adema -// Michael Pfeiffer -// -// This application and all source files used in its construction, except -// where noted, are licensed under the MIT License, and have been written -// and are: -// -// Copyright (c) 2001 OpenBeOS Project -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -/*****************************************************************************/ - -#ifndef BEUTILS_H -#define BEUTILS_H - -#include -#include -#include -#include -#include -#include -#include - -status_t TestForAddonExistence(const char* name, directory_which which, - const char* section, BPath& outPath); - -// Reference counted object -class Object { -private: - volatile int32 fRefCount; - -public: - // After construction reference count is 1 - Object() : fRefCount(1) { } - // dtor should be private, but ie. ObjectList requires a public dtor! - virtual ~Object() { }; - - // thread-safe as long as thread that calls Acquire has already - // a reference to the object - void Acquire() { - atomic_add(&fRefCount, 1); - } - - bool Release() { - if (atomic_add(&fRefCount, -1) == 1) { - delete this; return true; - } else { - return false; - } - } -}; - -// Automatically send a reply to sender on destruction of object -// and delete sender -class AutoReply { - BMessage* fSender; - BMessage fReply; - -public: - AutoReply(BMessage* sender, uint32 what); - ~AutoReply(); - void SetReply(BMessage* m) { fReply = *m; } -}; - -// mimetype from sender -bool MimeTypeForSender(BMessage* sender, BString& mime); -// adds fields to message or replaces existing fields -bool AddFields(BMessage* to, const BMessage* from); -// load bitmap from application resources -BBitmap* LoadBitmap(const char* name, uint32 type_code = B_TRANSLATOR_BITMAP); -// convert bitmap to picture; view must be attached to a window! -// returns NULL if bitmap is NULL -BPicture *BitmapToPicture(BView* view, BBitmap *bitmap); -BPicture *BitmapToGrayedPicture(BView* view, BBitmap *bitmap); -#endif diff --git a/src/servers/print/ConfigWindow.cpp b/src/servers/print/ConfigWindow.cpp index 52c7c385e3..b39d05572d 100644 --- a/src/servers/print/ConfigWindow.cpp +++ b/src/servers/print/ConfigWindow.cpp @@ -30,12 +30,15 @@ /*****************************************************************************/ +#include "pr_server.h" #include "Printer.h" #include "PrintServerApp.h" #include "ConfigWindow.h" #include "BeUtils.h" // posix +#include +#include #include #include @@ -44,6 +47,65 @@ #include #include +static const float a0_width = 2380.0; +static const float a0_height = 3368.0; +static const float a1_width = 1684.0; +static const float a1_height = 2380.0; +static const float a2_width = 1190.0; +static const float a2_height = 1684.0; +static const float a3_width = 842.0; +static const float a3_height = 1190.0; +static const float a4_width = 595.0; +static const float a4_height = 842.0; +static const float a5_width = 421.0; +static const float a5_height = 595.0; +static const float a6_width = 297.0; +static const float a6_height = 421.0; +static const float b5_width = 501.0; +static const float b5_height = 709.0; +static const float letter_width = 612.0; +static const float letter_height = 792.0; +static const float legal_width = 612.0; +static const float legal_height = 1008.0; +static const float ledger_width = 1224.0; +static const float ledger_height = 792.0; +static const float p11x17_width = 792.0; +static const float p11x17_height = 1224.0; + +static struct PageFormat +{ + char *label; + float width; + float height; +} pageFormat[] = +{ + {"Letter", letter_width, letter_height }, + {"Legal", legal_width, legal_height }, + {"Ledger", ledger_width, ledger_height }, + {"p11x17", p11x17_width, p11x17_height }, + {"A0", a0_width, a0_height }, + {"A1", a1_width, a1_height }, + {"A2", a2_width, a2_height }, + {"A3", a3_width, a3_height }, + {"A4", a4_width, a4_height }, + {"A5", a5_width, a5_height }, + {"A6", a6_width, a6_height }, + {"B5", b5_width, b5_height }, +}; + +static void GetPageFormat(float w, float h, BString& label) { + w = floor(w + 0.5); h = floor(h + 0.5); + for (int i = 0; i < sizeof(pageFormat) / sizeof(struct PageFormat); i ++) { + struct PageFormat& pf = pageFormat[i]; + if (pf.width == w && pf.height == h || pf.width == h && pf.height == w) { + label = pf.label; return; + } + } + + float unit = 72.0; // currently inc[h]es only + label << (w / unit) << "x" << (h / unit) << " in."; +} + ConfigWindow::ConfigWindow(config_setup_kind kind, Printer* defaultPrinter, BMessage* settings, AutoReply* sender) : BWindow(ConfigWindow::GetWindowFrame(), "Page Setup", B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE) @@ -81,8 +143,10 @@ ConfigWindow::ConfigWindow(config_setup_kind kind, Printer* defaultPrinter, BMes r.OffsetTo(left, top); fPageSetup = AddPictureButton(panel, r, "Page Format", "PAGE_SETUP_ON", "PAGE_SETUP_OFF", MSG_PAGE_SETUP); // add description to button - r.OffsetTo(left + fPageSetup->Bounds().Width() + 5, top + fPageSetup->Bounds().Height()/2-5); + r.OffsetTo(left + fPageSetup->Bounds().Width() + 5, top + 5); AddStringView(panel, r, "Setup page format"); + r.OffsetBy(0, 10); + fPageFormatText = AddStringView(panel, r, ""); top += fPageSetup->Bounds().Height() + 5; // page selection button @@ -91,8 +155,10 @@ ConfigWindow::ConfigWindow(config_setup_kind kind, Printer* defaultPrinter, BMes r.OffsetTo(left, top); fJobSetup = AddPictureButton(panel, r, "Page Selection", "JOB_SETUP_ON", "JOB_SETUP_OFF", MSG_JOB_SETUP); // add description to button - r.OffsetTo(left + fJobSetup->Bounds().Width() + 5, top + fJobSetup->Bounds().Width()/2-5); + r.OffsetTo(left + fJobSetup->Bounds().Width() + 5, top + 5); AddStringView(panel, r, "Setup print job"); + r.OffsetBy(0, 10); + fJobSetupText = AddStringView(panel, r, ""); top += fJobSetup->Bounds().Height() + 5; } top += 5; @@ -266,11 +332,13 @@ BPictureButton* ConfigWindow::AddPictureButton(BView* panel, BRect frame, const return button; } -void ConfigWindow::AddStringView(BView* panel, BRect frame, const char* text) { +BStringView* ConfigWindow::AddStringView(BView* panel, BRect frame, const char* text) { + // frame.bottom = frame.top ; BStringView* string = new BStringView(frame, "", text); string->SetViewColor(panel->ViewColor()); string->SetLowColor(panel->ViewColor()); panel->AddChild(string); + return string; } void ConfigWindow::PrinterForMimeType() { @@ -347,8 +415,12 @@ void ConfigWindow::UpdateSettings(bool read) { void ConfigWindow::UpdateUI() { if (fCurrentPrinter == NULL) { fPageSetup->SetEnabled(false); - if (fJobSetup) fJobSetup->SetEnabled(false); + if (fJobSetup) { + fJobSetup->SetEnabled(false); + fJobSetupText->SetText("Undefined job settings"); + } fOk->SetEnabled(false); + fPageFormatText->SetText("Undefined paper format"); } else { fPageSetup->SetEnabled(true); @@ -357,6 +429,43 @@ void ConfigWindow::UpdateUI() { } fOk->SetEnabled(fKind == kJobSetup && !fJobSettings.IsEmpty() || fKind == kPageSetup && !fPageSettings.IsEmpty()); + + // display information about page format + BRect paperRect; + BString pageFormat; + if (fPageSettings.FindRect(PSRV_FIELD_PAPER_RECT, &paperRect) == B_OK) { + GetPageFormat(paperRect.Width(), paperRect.Height(), pageFormat); + + int32 orientation = 0; + fPageSettings.FindInt32(PSRV_FIELD_ORIENTATION, &orientation); + if (orientation == 0) pageFormat << ", Portrait"; + else pageFormat << ", Landscape"; + } else { + pageFormat << "Undefined paper format"; + } + fPageFormatText->SetText(pageFormat.String()); + + // display information about job + if (fKind == kJobSetup) { + BString job; + int32 first, last, copies; + if (fJobSettings.FindInt32(PSRV_FIELD_FIRST_PAGE, &first) == B_OK && + fJobSettings.FindInt32(PSRV_FIELD_LAST_PAGE, &last) == B_OK) { + if (first >= 1 && first <= last && last != INT_MAX) { + job << "From page " << first << " to " << last; + } else { + job << "All pages"; + } + int32 copies; + if (fJobSettings.FindInt32(PSRV_FIELD_COPIES, &copies) == B_OK && copies > 1) { + job << ", " << copies << " copies"; + } + } else { + job << "Undefined job settings"; + } + + fJobSetupText->SetText(job.String()); + } } } diff --git a/src/servers/print/ConfigWindow.h b/src/servers/print/ConfigWindow.h index 8ea08bedcc..741fded5ad 100644 --- a/src/servers/print/ConfigWindow.h +++ b/src/servers/print/ConfigWindow.h @@ -65,7 +65,7 @@ public: private: BPictureButton* AddPictureButton(BView* panel, BRect frame, const char* name, const char* on, const char* off, uint32 what); - void AddStringView(BView* panel, BRect frame, const char* text); + BStringView* AddStringView(BView* panel, BRect frame, const char* text); void PrinterForMimeType(); void SetupPrintersMenu(BMenu* menu); void UpdateAppSettings(const char* mime, const char* printer); @@ -90,6 +90,8 @@ private: BPictureButton* fPageSetup; BPictureButton* fJobSetup; BButton* fOk; + BStringView* fPageFormatText; + BStringView* fJobSetupText; }; #endif diff --git a/src/servers/print/Jamfile b/src/servers/print/Jamfile index 0ac9dd2f04..afc42570cd 100644 --- a/src/servers/print/Jamfile +++ b/src/servers/print/Jamfile @@ -1,7 +1,10 @@ SubDir OBOS_TOP src servers print ; -UsePrivateHeaders interface ; -UsePrivateHeaders shared ; +SubInclude OBOS_TOP src servers print shared ; + +SubDir OBOS_TOP src servers print ; + +UsePrivateHeaders shared interface print ; AddResources print_server @@ -18,8 +21,6 @@ Server Printer.Scripting.cpp Printer.cpp ResourceManager.cpp - Jobs.cpp - BeUtils.cpp Settings.cpp ConfigWindow.cpp ; @@ -29,5 +30,6 @@ LinkSharedOSLibs : be root - translation + translation + libprint.a ; diff --git a/src/servers/print/PrintServerApp.R5.cpp b/src/servers/print/PrintServerApp.R5.cpp index 5e0b962d77..a9eea63f41 100644 --- a/src/servers/print/PrintServerApp.R5.cpp +++ b/src/servers/print/PrintServerApp.R5.cpp @@ -126,6 +126,38 @@ status_t PrintServerApp::async_thread(void* data) } } break; + + // Create a new printer + case PSRV_MAKE_PRINTER: { + BString driverName, transportName, transportPath; + BString printerName, connection; + + if (msg->FindString("driver", &driverName) == B_OK && + msg->FindString("transport", &transportName) == B_OK && + msg->FindString("transport path", &transportPath) == B_OK && + msg->FindString("printer name", &printerName) == B_OK + ) { + + if (msg->FindString("connection", &connection) != B_OK) + connection = "Local"; + + // then create the actual printer + if (p->app->CreatePrinter(printerName.String(), driverName.String(), + connection.String(), + transportName.String(), transportPath.String()) == B_OK) { + // If printer was created ok, ask if it needs to be the default + char buffer[256]; + ::sprintf(buffer, "Would you like to make %s the default\nprinter?", + printerName.String()); + + BAlert* alert = new BAlert("", buffer, "No", "Yes"); + if (alert->Go() == 1) { + p->app->SelectPrinter(printerName.String()); + } + } + } + } + break; } } @@ -180,6 +212,7 @@ void PrintServerApp::Handle_BeOSR5_Message(BMessage* msg) } break; +#if 0 // Create a new printer case PSRV_MAKE_PRINTER: { BString driverName, transportName, transportPath; @@ -211,10 +244,12 @@ void PrintServerApp::Handle_BeOSR5_Message(BMessage* msg) } } break; +#endif case PSRV_SHOW_PAGE_SETUP: case PSRV_SHOW_PRINT_SETUP: case PSRV_GET_DEFAULT_SETTINGS: + case PSRV_MAKE_PRINTER: AsyncHandleMessage(DetachCurrentMessage()); break; diff --git a/src/servers/print/PrintServerApp.Scripting.cpp b/src/servers/print/PrintServerApp.Scripting.cpp index d3e68ceca4..6a78b76824 100644 --- a/src/servers/print/PrintServerApp.Scripting.cpp +++ b/src/servers/print/PrintServerApp.Scripting.cpp @@ -13,7 +13,7 @@ // where noted, are licensed under the MIT License, and have been written // and are: // -// Copyright (c) 2001 OpenBeOS Project +// Copyright (c) 2001, 2002 OpenBeOS Project // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), diff --git a/src/servers/print/PrintServerApp.cpp b/src/servers/print/PrintServerApp.cpp index 65974aed69..a25a1e663d 100644 --- a/src/servers/print/PrintServerApp.cpp +++ b/src/servers/print/PrintServerApp.cpp @@ -14,7 +14,7 @@ // where noted, are licensed under the MIT License, and have been written // and are: // -// Copyright (c) 2001 OpenBeOS Project +// Copyright (c) 2001, 2002 OpenBeOS Project // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -112,7 +112,8 @@ PrintServerApp::PrintServerApp(status_t* err) fSelectedIconLarge(NULL), fReferences(0), fHasReferences(0), - fUseConfigWindow(true) + fUseConfigWindow(true), + fFolder(NULL) { fSettings = Settings::GetSettings(); LoadSettings(); @@ -151,6 +152,8 @@ bool PrintServerApp::QuitRequested() bool rc = Inherited::QuitRequested(); if (rc) { + delete fFolder; fFolder = NULL; +#if 0 // Find directory containing printer definition nodes BPath path; if (::find_directory(B_USER_PRINTERS_DIRECTORY, &path) == B_OK) { @@ -162,6 +165,7 @@ bool PrintServerApp::QuitRequested() ::watch_node(&nref, B_STOP_WATCHING, be_app_messenger); } } +#endif // Release all printers Printer* printer; @@ -195,18 +199,28 @@ void PrintServerApp::Release() { } void PrintServerApp::RegisterPrinter(BDirectory* printer) { - BString transport, address, connection; + BString transport, address, connection, state; - printer->ReadAttrString(PSRV_PRINTER_ATTR_TRANSPORT, &transport); - printer->ReadAttrString(PSRV_PRINTER_ATTR_TRANSPORT_ADDR, &address); - printer->ReadAttrString(PSRV_PRINTER_ATTR_CNX, &connection); + if (printer->ReadAttrString(PSRV_PRINTER_ATTR_TRANSPORT, &transport) == B_OK && + printer->ReadAttrString(PSRV_PRINTER_ATTR_TRANSPORT_ADDR, &address) == B_OK && + printer->ReadAttrString(PSRV_PRINTER_ATTR_CNX, &connection) == B_OK && + printer->ReadAttrString(PSRV_PRINTER_ATTR_STATE, &state) == B_OK && + state == "free") { - BAutolock lock(gLock); - if (lock.IsLocked()) { - Resource* r = fResourceManager.Allocate(transport.String(), address.String(), connection.String()); - Printer* p = new Printer(printer, r); - AddHandler(p); - Acquire(); + BAutolock lock(gLock); + if (lock.IsLocked()) { + // check if printer is already registered + node_ref node; + Printer* p; + if (printer->GetNodeRef(&node) != B_OK) return; + p = Printer::Find(&node); + if (p != NULL) return; + // register new printer + Resource* r = fResourceManager.Allocate(transport.String(), address.String(), connection.String()); + p = new Printer(printer, r); + AddHandler(p); + Acquire(); + } } } @@ -224,20 +238,29 @@ void PrintServerApp::NotifyPrinterDeletion(Printer* printer) { } } -void PrintServerApp::HandleRemovedPrinter(BMessage* msg) { - int32 opcode; - dev_t device; - ino_t node; - Printer* printer; - if (msg->FindInt32("opcode", &opcode) == B_OK && opcode == B_ENTRY_REMOVED && - msg->FindInt32("device", &device) == B_OK && - msg->FindInt64("node", &node) == B_OK && - (printer = Printer::Find(device, node)) != NULL) { + +void PrintServerApp::EntryCreated(node_ref* node, entry_ref* entry) { + BEntry printer(entry); + if (printer.InitCheck() == B_OK && printer.IsDirectory()) { + BDirectory dir(&printer); + if (dir.InitCheck() == B_OK) RegisterPrinter(&dir); + } +} + +void PrintServerApp::EntryRemoved(node_ref* node) { + Printer* printer = Printer::Find(node); + if (printer) { if (printer == fDefaultPrinter) fDefaultPrinter = NULL; UnregisterPrinter(printer); } } +void PrintServerApp::AttributeChanged(node_ref* node) { + BDirectory printer(node); + if (printer.InitCheck() == B_OK) { + RegisterPrinter(&printer); + } +} // --------------------------------------------------------------- // SetupPrinterList @@ -280,7 +303,11 @@ status_t PrintServerApp::SetupPrinterList() } } } - + + + fFolder = new FolderWatcher(this, dir, true); + fFolder->SetListener(this); +#if 0 // If we scanned all entries successfully node_ref nref; if (rc == B_ENTRY_NOT_FOUND && @@ -288,6 +315,7 @@ status_t PrintServerApp::SetupPrinterList() // Get node to watch rc = ::watch_node(&nref, B_WATCH_DIRECTORY, be_app_messenger); } +#endif } } @@ -328,10 +356,6 @@ PrintServerApp::MessageReceived(BMessage* msg) case B_EXECUTE_PROPERTY: HandleScriptingCommand(msg); break; - - case B_NODE_MONITOR: - HandleRemovedPrinter(msg); - break; default: Inherited::MessageReceived(msg); @@ -378,7 +402,6 @@ PrintServerApp::CreatePrinter(const char* printerName, const char* driverName, // Store the settings in its attributes printer.WriteAttr(PSRV_PRINTER_ATTR_PRT_NAME, B_STRING_TYPE, 0, printerName, ::strlen(printerName)+1); printer.WriteAttr(PSRV_PRINTER_ATTR_DRV_NAME, B_STRING_TYPE, 0, driverName, ::strlen(driverName)+1); - printer.WriteAttr(PSRV_PRINTER_ATTR_STATE, B_STRING_TYPE, 0, "free", ::strlen("free")+1); printer.WriteAttr(PSRV_PRINTER_ATTR_TRANSPORT, B_STRING_TYPE, 0, transportName,::strlen(transportName)+1); printer.WriteAttr(PSRV_PRINTER_ATTR_TRANSPORT_ADDR, B_STRING_TYPE, 0, transportPath,::strlen(transportPath)+1); printer.WriteAttr(PSRV_PRINTER_ATTR_CNX, B_STRING_TYPE, 0, connection, ::strlen(connection)+1); @@ -399,7 +422,7 @@ PrintServerApp::CreatePrinter(const char* printerName, const char* driverName, entry.Remove(); } } else { - RegisterPrinter(&printer); + printer.WriteAttr(PSRV_PRINTER_ATTR_STATE, B_STRING_TYPE, 0, "free", ::strlen("free")+1); } } diff --git a/src/servers/print/PrintServerApp.h b/src/servers/print/PrintServerApp.h index 8f1576b0f5..83199d4d55 100644 --- a/src/servers/print/PrintServerApp.h +++ b/src/servers/print/PrintServerApp.h @@ -14,7 +14,7 @@ // where noted, are licensed under the MIT License, and have been written // and are: // -// Copyright (c) 2001 OpenBeOS Project +// Copyright (c) 2001, 2002 OpenBeOS Project // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -40,6 +40,7 @@ #include "ResourceManager.h" #include "Settings.h" +#include "FolderWatcher.h" class PrintServerApp; @@ -57,7 +58,7 @@ extern BLocker* gLock; // Application class for print_server. /*****************************************************************************/ class Printer; -class PrintServerApp : public BApplication +class PrintServerApp : public BApplication, public FolderListener { typedef BApplication Inherited; public: @@ -93,8 +94,11 @@ private: void RegisterPrinter(BDirectory* node); void UnregisterPrinter(Printer* printer); - void HandleRemovedPrinter(BMessage* msg); - + // FolderListener + void EntryCreated(node_ref* node, entry_ref* entry); + void EntryRemoved(node_ref* node); + void AttributeChanged(node_ref* node); + status_t StoreDefaultPrinter(); status_t RetrieveDefaultPrinter(); @@ -109,6 +113,7 @@ private: sem_id fHasReferences; Settings*fSettings; bool fUseConfigWindow; + FolderWatcher* fFolder; // "Classic" BeOS R5 support, see PrintServerApp.R5.cpp static status_t async_thread(void* data); diff --git a/src/servers/print/Printer.Scripting.cpp b/src/servers/print/Printer.Scripting.cpp index 993d209457..d971946035 100644 --- a/src/servers/print/Printer.Scripting.cpp +++ b/src/servers/print/Printer.Scripting.cpp @@ -13,7 +13,7 @@ // where noted, are licensed under the MIT License, and have been written // and are: // -// Copyright (c) 2001 OpenBeOS Project +// Copyright (c) 2001, 2002 OpenBeOS Project // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), diff --git a/src/servers/print/Printer.cpp b/src/servers/print/Printer.cpp index 2c96b34a05..74a9994a64 100644 --- a/src/servers/print/Printer.cpp +++ b/src/servers/print/Printer.cpp @@ -55,6 +55,23 @@ #include #include + +SpoolFolder::SpoolFolder(BLocker*locker, BLooper* looper, const BDirectory& spoolDir) + : Folder(locker, looper, spoolDir) +{ +} + + +// Notify print_server that there is a job file waiting for printing +void SpoolFolder::Notify(Job* job, int kind) +{ + if ((kind == kJobAdded || kind == kJobAttrChanged) && + job->IsValid() && job->IsWaiting()) { + be_app_messenger.SendMessage(PSRV_PRINT_SPOOLED_JOB); + } +} + + // --------------------------------------------------------------- typedef BMessage* (*config_func_t)(BNode*, const BMessage*); typedef BMessage* (*take_job_func_t)(BFile*, BNode*, const BMessage*); @@ -90,14 +107,14 @@ Printer* Printer::Find(const BString& name) return NULL; } -Printer* Printer::Find(dev_t dev, ino_t node) +Printer* Printer::Find(node_ref* node) { + node_ref n; // Look in list to find printer definition for (int32 idx=0; idx < sPrinters.CountItems(); idx++) { Printer* printer = sPrinters.ItemAt(idx); - node_ref ref; - printer->SpoolDir()->GetNodeRef(&ref); - if (ref.device == dev && ref.node == node) return printer; + printer->SpoolDir()->GetNodeRef(&n); + if (n == *node) return printer; } // None found, so return NULL @@ -132,7 +149,7 @@ int32 Printer::CountPrinters() // --------------------------------------------------------------- Printer::Printer(const BDirectory* node, Resource* res) : Inherited(B_EMPTY_STRING), - fPrinter(*node), + fPrinter(gLock, be_app, *node), fResource(res), fSinglePrintThread(true), fJob(NULL), diff --git a/src/servers/print/Printer.h b/src/servers/print/Printer.h index e3e506cdea..9e3940cdb0 100644 --- a/src/servers/print/Printer.h +++ b/src/servers/print/Printer.h @@ -14,7 +14,7 @@ // where noted, are licensed under the MIT License, and have been written // and are: // -// Copyright (c) 2001 OpenBeOS Project +// Copyright (c) 2001, 2002 OpenBeOS Project // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), @@ -55,6 +55,14 @@ class Printer; // OpenTracker shared sources #include "ObjectList.h" +class SpoolFolder : public Folder { +protected: + void Notify(Job* job, int kind); + +public: + SpoolFolder(BLocker* locker, BLooper* looper, const BDirectory& spoolDir); +}; + /*****************************************************************************/ // Printer // @@ -71,7 +79,7 @@ public: // Static helper functions static Printer* Find(const BString& name); - static Printer* Find(dev_t device, ino_t node); + static Printer* Find(node_ref* node); static Printer* At(int32 idx); static void Remove(Printer* printer); static int32 CountPrinters(); @@ -102,11 +110,11 @@ private: status_t LoadPrinterAddon(image_id& id); void AddCurrentPrinter(BMessage* m); - Folder fPrinter; // the printer spooling directory Resource* fResource; // the resource required for processing a print job + SpoolFolder fPrinter; // the printer spooling directory bool fSinglePrintThread; // is printer add-on allowed to process multiple print job at once Job* fJob; // the next job to process - vint32 fProcessing; // the current number of processing threads + vint32 fProcessing; // the current nmber of processing threads bool fAbort; // stop processing static BObjectList sPrinters; diff --git a/src/servers/print/BeUtils.cpp b/src/servers/print/shared/BeUtils.cpp similarity index 98% rename from src/servers/print/BeUtils.cpp rename to src/servers/print/shared/BeUtils.cpp index 6aafbfc442..c1bd9e12f9 100644 --- a/src/servers/print/BeUtils.cpp +++ b/src/servers/print/shared/BeUtils.cpp @@ -15,7 +15,7 @@ // where noted, are licensed under the MIT License, and have been written // and are: // -// Copyright (c) 2001 OpenBeOS Project +// Copyright (c) 2001, 2002 OpenBeOS Project // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), diff --git a/src/servers/print/shared/FolderWatcher.cpp b/src/servers/print/shared/FolderWatcher.cpp new file mode 100644 index 0000000000..7c1ec99db1 --- /dev/null +++ b/src/servers/print/shared/FolderWatcher.cpp @@ -0,0 +1,175 @@ +/*****************************************************************************/ +// FolderWatcher +// +// Author +// Michael Pfeiffer +// +// This application and all source files used in its construction, except +// where noted, are licensed under the MIT License, and have been written +// and are: +// +// Copyright (c) 2002 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + + +#include "FolderWatcher.h" + +#include + +// BeOS +#include +#include +#include +#include + + +// Implementation of FolderWatcher + +FolderWatcher::FolderWatcher(BLooper* looper, const BDirectory& folder, bool watchAttrChanges) + : fFolder(folder) + , fListener(NULL) + , fWatchAttrChanges(watchAttrChanges) +{ + // add this handler to the application for node monitoring + if (looper->Lock()) { + looper->AddHandler(this); + looper->Unlock(); + } + + // start attribute change watching for existing files + if (watchAttrChanges) { + BEntry entry; + node_ref node; + while (fFolder.GetNextEntry(&entry) == B_OK && entry.GetNodeRef(&node) == B_OK) { + StartAttrWatching(&node); + } + } + + // start watching the spooler directory + node_ref ref; + fFolder.GetNodeRef(&ref); + watch_node(&ref, B_WATCH_DIRECTORY, this); +} + +FolderWatcher::~FolderWatcher() { + // stop node watching for spooler directory + node_ref ref; + fFolder.GetNodeRef(&ref); + watch_node(&ref, B_STOP_WATCHING, this); + // stop sending notifications to this handler + stop_watching(this); + + if (LockLooper()) { + BLooper* looper = Looper(); + // and remove it + looper->RemoveHandler(this); + looper->Unlock(); + } +} + +void FolderWatcher::SetListener(FolderListener* listener) { + fListener = listener; +} + +bool FolderWatcher::BuildEntryRef(BMessage* msg, const char* dirName, entry_ref* entry) { + const char* name; + if (msg->FindInt32("device", &entry->device) == B_OK && + msg->FindInt64(dirName, &entry->directory) == B_OK && + msg->FindString("name", &name) == B_OK) { + entry->set_name(name); + return true; + } + return false; +} + +bool FolderWatcher::BuildNodeRef(BMessage* msg, node_ref* node) { + return (msg->FindInt32("device", &node->device) == B_OK && + msg->FindInt64("node", &node->node) == B_OK); +} + +void FolderWatcher::HandleCreatedEntry(BMessage* msg, const char* dirName) { + node_ref node; + entry_ref entry; + if (BuildEntryRef(msg, dirName, &entry) && + BuildNodeRef(msg, &node)) { + if (fWatchAttrChanges) StartAttrWatching(&node); + fListener->EntryCreated(&node, &entry); + } +} + +void FolderWatcher::HandleRemovedEntry(BMessage* msg) { + node_ref node; + if (BuildNodeRef(msg, &node)) { + if (fWatchAttrChanges) StopAttrWatching(&node); + fListener->EntryRemoved(&node); + } +} + +void FolderWatcher::HandleChangedAttr(BMessage* msg) { + node_ref node; + if (BuildNodeRef(msg, &node)) { + fListener->AttributeChanged(&node); + } +} + +void FolderWatcher::MessageReceived(BMessage* msg) { + int32 opcode; + node_ref folder; + ino_t dir; + + if (msg->what == B_NODE_MONITOR) { + if (fListener == NULL || msg->FindInt32("opcode", &opcode) != B_OK) return; + + switch (opcode) { + case B_ENTRY_CREATED: + HandleCreatedEntry(msg, "directory"); + break; + case B_ENTRY_REMOVED: + HandleRemovedEntry(msg); + break; + case B_ENTRY_MOVED: + fFolder.GetNodeRef(&folder); + if (msg->FindInt64("to directory", &dir) == B_OK && folder.node == dir) { + // entry moved into this folder + HandleCreatedEntry(msg, "to directory"); + } else if (msg->FindInt64("from directory", &dir) == B_OK && folder.node == dir) { + // entry removed from this folder + HandleRemovedEntry(msg); + } + break; + case B_ATTR_CHANGED: + HandleChangedAttr(msg); + break; + default: // nothing to do + break; + } + } else { + inherited::MessageReceived(msg); + } +} + +status_t FolderWatcher::StartAttrWatching(node_ref* node) { + return watch_node(node, B_WATCH_ATTR, this); +} + +status_t FolderWatcher::StopAttrWatching(node_ref* node) { + return watch_node(node, B_STOP_WATCHING, this); +} diff --git a/src/servers/print/shared/Jamfile b/src/servers/print/shared/Jamfile new file mode 100644 index 0000000000..029566e73f --- /dev/null +++ b/src/servers/print/shared/Jamfile @@ -0,0 +1,11 @@ +SubDir OBOS_TOP src servers print shared ; + +UsePrivateHeaders shared interface print ; + +StaticLibrary + print + : + BeUtils.cpp + FolderWatcher.cpp + Jobs.cpp + ; diff --git a/src/servers/print/shared/Jobs.cpp b/src/servers/print/shared/Jobs.cpp new file mode 100644 index 0000000000..bbf16fa14d --- /dev/null +++ b/src/servers/print/shared/Jobs.cpp @@ -0,0 +1,265 @@ +/*****************************************************************************/ +// Jobs +// +// Author +// Michael Pfeiffer +// +// This application and all source files used in its construction, except +// where noted, are licensed under the MIT License, and have been written +// and are: +// +// Copyright (c) 2002 OpenBeOS Project +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +/*****************************************************************************/ + + +#include "pr_server.h" +#include "Jobs.h" +// #include "PrintServerApp.h" + +// posix +#include +#include + +// BeOS +#include +#include +#include +#include +#include + + +// Implementation of Job + +Job::Job(const BEntry& job, Folder* folder) + : fFolder(folder) + , fTime(-1) + , fStatus(kUnknown) + , fValid(false) + , fPrinter(NULL) +{ + // store light weight versions of BEntry and BNode + job.GetRef(&fEntry); + job.GetNodeRef(&fNode); + + fValid = IsValidJobFile(); + + BNode node(&job); + if (node.InitCheck() != B_OK) return; + + BString status; + // read status attribute + if (node.ReadAttrString(PSRV_SPOOL_ATTR_STATUS, &status) != B_OK) { + status = ""; + } + UpdateStatus(status.String()); + + // Now get file name and creation time from file name + fTime = 0; + BEntry entry(job); + char name[B_FILE_NAME_LENGTH]; + if (entry.InitCheck() == B_OK && entry.GetName(name) == B_OK) { + fName = name; + // search for last '@' in file name + char* p = NULL, *c = name; + while ((c = strchr(c, '@')) != NULL) { + p = c; c ++; + } + // and get time from file name + if (p) fTime = atoi(p+1); + } +} + +// conversion from string representation of status to JobStatus constant +void Job::UpdateStatus(const char* status) { + if (strcmp(status, PSRV_JOB_STATUS_WAITING) == 0) fStatus = kWaiting; + else if (strcmp(status, PSRV_JOB_STATUS_PROCESSING) == 0) fStatus = kProcessing; + else if (strcmp(status, PSRV_JOB_STATUS_FAILED) == 0) fStatus = kFailed; + else if (strcmp(status, PSRV_JOB_STATUS_COMPLETED) == 0) fStatus = kCompleted; + else fStatus = kUnknown; +} + +// Write to status attribute of node +void Job::UpdateStatusAttribute(const char* status) { + BNode node(&fEntry); + if (node.InitCheck() == B_OK) { + node.WriteAttr(PSRV_SPOOL_ATTR_STATUS, B_STRING_TYPE, 0, status, strlen(status)+1); + } +} + + +bool Job::HasAttribute(BNode* n, const char* name) { + attr_info info; + return n->GetAttrInfo(name, &info) == B_OK; +} + + +bool Job::IsValidJobFile() { + BNode node(&fEntry); + if (node.InitCheck() != B_OK) return false; + + BNodeInfo info(&node); + char mimeType[256]; + + // Is job a spool file? + return (info.InitCheck() == B_OK && + info.GetType(mimeType) == B_OK && + strcmp(mimeType, PSRV_SPOOL_FILETYPE) == 0) && + HasAttribute(&node, PSRV_SPOOL_ATTR_MIMETYPE) && + HasAttribute(&node, PSRV_SPOOL_ATTR_PAGECOUNT) && + HasAttribute(&node, PSRV_SPOOL_ATTR_DESCRIPTION) && + HasAttribute(&node, PSRV_SPOOL_ATTR_PRINTER) && + HasAttribute(&node, PSRV_SPOOL_ATTR_STATUS); +} + + +// Set status of object and optionally write to attribute of node +void Job::SetStatus(JobStatus s, bool writeToNode) { + fStatus = s; + if (!writeToNode) return; + switch (s) { + case kWaiting: UpdateStatusAttribute(PSRV_JOB_STATUS_WAITING); break; + case kProcessing: UpdateStatusAttribute(PSRV_JOB_STATUS_PROCESSING); break; + case kFailed: UpdateStatusAttribute(PSRV_JOB_STATUS_FAILED); break; + case kCompleted: UpdateStatusAttribute(PSRV_JOB_STATUS_COMPLETED); break; + default: break; + } +} + +// Synchronize file attribute with member variable +void Job::UpdateAttribute() { + fValid = fValid || IsValidJobFile(); + BNode node(&fEntry); + BString status; + if (node.InitCheck() == B_OK && + node.ReadAttrString(PSRV_SPOOL_ATTR_STATUS, &status) == B_OK) { + UpdateStatus(status.String()); + } +} + +void Job::Remove() { + BEntry entry(&fEntry); + if (entry.InitCheck() == B_OK) entry.Remove(); +} + +// Implementation of Folder + +// BObjectList CompareFunction +int Folder::AscendingByTime(const Job* a, const Job* b) { + return a->Time() - b->Time(); +} + +bool Folder::AddJob(BEntry& entry, bool notify) { + Job* job = new Job(entry, this); + if (job->InitCheck() == B_OK) { + fJobs.AddItem(job); + if (notify) Notify(job, kJobAdded); + return true; + } else { + job->Release(); + return false; + } +} + +// simplified assumption that ino_t identifies job file +// will probabely not work in all cases with link to a file on another volume??? +Job* Folder::Find(node_ref* node) { + for (int i = 0; i < fJobs.CountItems(); i ++) { + Job* job = fJobs.ItemAt(i); + if (job->NodeRef() == *node) return job; + } + return NULL; +} + +void Folder::EntryCreated(node_ref* node, entry_ref* entry) { + BEntry job(entry); + if (job.InitCheck() == B_OK && Lock()) { + if (AddJob(job)) { + fJobs.SortItems(AscendingByTime); + } + Unlock(); + } +} + +void Folder::EntryRemoved(node_ref* node) { + Job* job = Find(node); + if (job && Lock()) { + fJobs.RemoveItem(job); + Notify(job, kJobRemoved); + job->Release(); + Unlock(); + } +} + +void Folder::AttributeChanged(node_ref* node) { + Job* job = Find(node); + if (job && Lock()) { + job->UpdateAttribute(); + Notify(job, kJobAttrChanged); + Unlock(); + } +} + +// initial setup of job list +void Folder::SetupJobList() { + if (inherited::Folder()->InitCheck() == B_OK) { + inherited::Folder()->Rewind(); + + BEntry entry; + while (inherited::Folder()->GetNextEntry(&entry) == B_OK) { + AddJob(entry, false); + } + fJobs.SortItems(AscendingByTime); + } +} + +Folder::Folder(BLocker* locker, BLooper* looper, const BDirectory& spoolDir) + : fLocker(locker) + , FolderWatcher(looper, spoolDir, true) + , fJobs() +{ + SetListener(this); + if (Lock()) { + SetupJobList(); + Unlock(); + } +} + + +Folder::~Folder() { + if (!Lock()) return; + // release jobs + for (int i = 0; i < fJobs.CountItems(); i ++) { + Job* job = fJobs.ItemAt(i); + job->Release(); + } + Unlock(); +} + +Job* Folder::GetNextJob() { + for (int i = 0; i < fJobs.CountItems(); i ++) { + Job* job = fJobs.ItemAt(i); + if (job->IsValid() && job->IsWaiting()) { + job->Acquire(); return job; + } + } + return NULL; +} +