以下、図面を参照しながら発明を実施するための形態について詳細に説明する。
以下で引用されるオペレーティングシステム(OS)の情報の内、特に詳しく説明していないものに関しては、インターネット上で公開されている情報であるので、必要以上の説明を省略する。2010年4月12日現在、Microsoft Developer Network (MSDN)のサイトで公開されている。http://msdn.microsoft.com/en-us/library/default.aspx
以下において、WSDとは、Web Service on Devicesを表し、インターネット上で公開されている情報であるので、必要以上の説明を省略する。2010年4月12日現在、Windows Hardware Developer Centralのサイトで公開されている。http://www.microsoft.com/whdc/connect/rally/rallywsd.mspx
以下において、WSDのPrint Service Definition Version 1.0は、インターネット上で公開されているので、必要以上の説明を省略する。2010年4月12日現在、Windows Hardware Developer Centralのサイトで公開されている米国マイクロソフト社が定義したPrint Serviceである。http://www.microsoft.com/whdc/connect/rally/wsdspecs.mspx
<実施形態1>
図1は情報処理装置及び周辺装置からなる周辺装置制御システムの一実施形態におけるシステムの構成を表すブロック図である。図1に示す情報処理装置1、2、5、888は、一般的なパーソナルコンピュータ(PC)で構成される。PC1、2、5、888は、図2(a)で後述するようなハードウェアで構成される。PC1、2、5、888には、OSとして米国マイクロソフト社のWindows 7(登録商標)と同等のOSがインストールされている。また、PC1、2、5、888はそれぞれEthernet(登録商標)で構成されるネットワーク4に接続されている。
プリンタ3は、カラーインクジェットプリンタで構成され、本発明における周辺装置の一例として構成されている。プリンタ3は、ABC社製のKmmnというモデル名のプリンタである。尚、周辺装置は、プリンタに限らず、複写機、ファクシミリ、スキャナ、デジタルカメラ、デジタルビデオカメラ、及びこれらの複合機能を備える装置等であっても良い。プリンタ3は、図2(b)で後述するようなハードウェアで構成され、PC1、2、5、888とネットワーク4を介して接続され、互いに双方向通信が可能である。
プリントアプリケーション30は、Windows(登録商標)用の実行可能形式のファイル(*.EXE)で構成される。尚、プリントアプリケーション30及びランゲージモニタ36は、図4を用いて更に詳細に説明する。
図2は、PCとプリンタのハードウェア構成の一例を表すブロック図である。PC1、2、5、888は、図2の(a)に示すようなハードウェアで構成されている。ここでは、PC5を例に挙げて説明する。図2の(a)に示すように、PC5にはRAM201、記憶部であるHDD202、入力部の一例であるKBD203、制御部のCPU204、表示部の一例であるLCD205、通信制御部の一例であるNB207が含まれ、バス206に接続されている。尚、記憶部は、可搬性CD−ROM又は内部据付のROMなどであっても良い。
図3、図4に示す各モジュール(ソフトウェア)は、HDD202に記憶され、必要に応じてRAM201に読み出されてCPU204により実行される。これにより、CPU204が、図3、図4に示す各モジュール(ソフトウェア)の機能を実現する。
一方、プリンタ3は、図2(b)に示すようなハードウェア構成を持つ。図2(b)に示すCPU15はマイクロプロセッサ等から構成され、プリンタ3の中央処理装置としてROM16に記憶されているプログラムに従ってRAM17、通信部18、記録部19、操作部20、表示部21を制御する。
ROM16にはプリンタドライバ(図4で後述する)の制御に従ってプリンタ3が記録(印刷)処理や、印刷動作の状態をPC5へ通知する処理を行うプログラムが記憶されている。RAM17は主にPC5から送られ、それをもとに記録部19によって印刷される印字データが一時的に記憶される。通信部18にはネットワーク4用の接続ポート等が含まれ、Ethernet(登録商標)通信を制御する。記録部19は、インクジェット方式の記録ヘッド、各カラーインク、キャリッジ、記録紙搬送機構等から構成される記録ユニットと、印字データをもとに記録ヘッドにて印字用パルスを発生させる為のASIC等から構成される電気回路とから構成される。
印刷可能なアプリケーション上での印刷操作によってアプリケーションで開かれているファイルの表示内容(画像データ)がEMF形式のスプールファイルとしてPC5のHDD202に一時的に格納される。格納されたスプールファイルは、プリンタドライバ50を介してプリンタ3制御用コマンドを含む印字データに変換された後、ネットワーク4を介してプリンタ3に送られる。プリンタ3で受信された印字データは、記録部19で印字用パルスに変換されて記録紙上に印刷される。
操作部20は、電源ボタン、リセットボタン等の各種ボタンから構成され、プリンタ3を操作することができる。表示部21は、タッチパネルの液晶ディスプレイで構成され、プリンタ3の状態の表示や、各種設定の表示、入力等を行うことができる。
図3は、PCのソフトウェア構成を表す図である。図3に示す、イーサネット(登録商標)制御スタック92はイーサネット(登録商標)を制御する。IPネットワーク制御スタック91はIPネットワークを制御する。WSD制御スタック90はWSDを制御する。IHVネイティブプロトコル制御スタック89はIHVの独自プロトコルを制御する。N−PnP制御スタック88はネットワークのプラグアンドプレイ(N−PnP)を制御する。
尚、ネットワーク接続デバイスに対するサポートを提供するプラグアンドプレイの一連の拡張機能としてOSに標準搭載されている機能には、PnP−X(Plug and Play for Extensions)が存在する。しかし、ここでは、これと同等の機能としてN−PnPを利用する例で説明する。
また、後述するWSDを制御するWSDAPIsは、WSD制御スタック90に含まれる。そして、後述するIHVの独自プロトコルを制御するAPIsは、IHVネイティブプロトコル制御スタック89に含まれる。
デバイスドライバ群85は、OSに標準で同梱されている標準ドライバ群87とIHVから提供されるIHV製ドライバ群86から構成される。アプリケーション/DDIインタフェース84は、アプリケーションプログラミングインタフェース(API)、デバイスドライバインタフェース(DDI)から構成される。アプリケーション群82は、図4で後述する印刷可能なアプリケーション30等から構成される。
図4は、PCにおけるプリンタドライバの構成を表す図である。図4に示す、プリンタドライバ50はPC5にインストールされているプリンタ3用のプリンタドライバであり、複数のモジュール33〜36、39から構成される。また、プリントアプリケーション30は、例えばOSに標準で同梱されている印刷可能なテキストエディタのノートパッド(Notepad.exe)等に相当する。そして、GDI(グラフィックスデバイスインタフェース)31及びスプーラ40はOSの一部であり、プリンタキュー32はこのスプーラ40の一部として構成され、印刷ジョブがキューイングされる。キューイングされた印刷ジョブはプリンタキューフォルダ(不図示)に表示される。
プリンタドライバ50において、プリントプロセッサ33は、印刷レイアウトの変更や印刷画像に対する特殊処理を行う。グラフィックスドライバ34は、プリンタドライバの画像処理のコアとしてGDI31から送られてくる描画命令をもとに印刷用の画像処理を行い、印刷制御コマンドを作成する。UIモジュール35は、プリンタドライバのユーザインタフェースの提供及び制御を行う。
また、ランゲージモニタ36は、データの通信I/Fとしてデータの送受信を制御する。ステータスモニタ39は、プリンタ3のインク残量や警告、エラー等の状態を表示する。ポートモニタ37は、ランゲージモニタ36から送られてくるデータを適切なポートに送信し、プリンタ3から送られてくるデータをクラスドライバ38を介して受信する処理を行う。特に、WSDのプリントサービスを制御するポートモニタのことをWSDMonと呼ぶ。
クラスドライバ38は、最もポートに近いローレベルのモジュールである。ここでは、WSDやIHVの独自プロトコルのプリンタクラスのドライバに相当し、ポート(ネットワークポート)を制御する。プリンタドライバ50は、プリンタ3の製造元であるABC社製のものである。
図10は、プリンタ3がPCに通知するWSDのイベントを管理するイベント管理データベースと、プリンタ3が受信した印刷ジョブ要求を管理する印刷キューデータベースを表す図である。図10は本発明の特徴を最も良く表す図の内の1つである。
図10の(a)は、プリンタ3がPCに通知するWSDのイベントを管理するイベント管理データベースを表す図である。一般的に、プリンタがPCに通知するイベントの制御に関しては、そのプリンタのハードウェアリソースにおける制限の影響を大きく受ける。具体的な例を挙げると、例えばプリンタが、同一ネットワーク上に存在する全てのPCに対して印刷ジョブの処理状況等をイベントによって通知することは困難である。そのため、一般的に、プリンタは自分で制御可能な特定の台数のPCに限定し、イベントの通知を行うように設計されている。
図10の(a)に示すイベント管理データベース123の場合、プリンタ3はComputer Name欄にセットされている最多で2台のPCに対してイベントを通知することが可能である。また、Subscribed Event欄には、PCからのWSDの各イベントの登録要求に対して、プリンタ3が登録を許可したイベントがセットされている。更に、ans:EventControl欄には、図8に示すWSDのGetPrinterElementsResponse内の<ans:EventControl>要素802にセットされる値が保存されている。この例では、プリンタ3がPC1、PC2に対して、以下に示すWSDの各イベントを通知することが可能な状態であることを示している。
PrinterElementsChangeEvent
PrinterStatusSummaryEvent
PrinterStatusConditionEvent
PrinterStatusConditionClearedEvent
JobStatusEvent
JobEndStateEvent
例えば、PC1又はPC2からプリンタ3に対して印刷ジョブが発行された場合、プリンタ3におけるその印刷ジョブの処理状況に応じて、プリンタ3はPC1又はPC2に対して、各イベントによる通知を行う。これにより、PC1又はPC2は、自分が発行した印刷ジョブの処理状況を把握することができる。
これに対して、PC5からプリンタ3に対して印刷ジョブが発行された場合、プリンタ3はこの印刷ジョブを受け付けて印刷を行うことができるものの、PC5に対して、その印刷ジョブの処理状況に応じた各イベントの通知を行うことができない。その結果、PC5は、自分が発行した印刷ジョブの処理状況を、イベントを利用して把握することはできない。これは、PC1、PC2、PC5からほぼ同時に印刷ジョブが発行された時に限定されることはなく、例えばネットワーク4上にPC1、PC2、PC5が存在する場合において、PC5だけから印刷ジョブが発行された場合にも同様である。プリンタ3はPC5に対してその印刷ジョブの処理状況に応じた各イベントの通知を行うことができない。この例では、特に重要なイベントとして、印刷ジョブの処理状況を表すJobStatusEventと、印刷が終了したことを表すJobEndStateEventの2つのイベントに着目する。このJobEndStateEventの詳細に関しては、図22を用いて更に説明する。
図10の(b)は、複数の印刷ジョブを同時に受け付けて処理することができず、1つの印刷ジョブだけを受け付けて処理することができるプリンタ3における、受信した印刷ジョブ要求を管理する印刷キューデータベースを表す図である。
印刷キューデータベース124において、管理番号(No.)欄は、印刷キューデータベース124における印刷ジョブ要求の管理番号である。この例では、プリンタ3が印刷処理中又は印刷処理待ちの印刷ジョブ要求を同時に5つまで保存することができる。次のComputer Name欄には、印刷ジョブ要求が発行されたPCの名前が保存されている。wprt:JobName欄には、WSDのプリントサービスのCreatePrintJobRequest内の<wprt:JobName>要素にセットされている値が保存されている。wprt:JobOriginatingUserName欄には、WSDのプリントサービスのCreatePrintJobRequest内の<wprt:JobOriginatingUserName>要素にセットされている値が保存されている。wprt:JobId欄には、前記印刷ジョブ要求に対する応答としてPCに返されるWSDのCreatePrintJobResponse内の<wprt:JobId>要素にセットされる値が保存されている。
管理番号が1の印刷ジョブ要求のwprt:JobIdの値1001は、プリンタ3がPC5から発行された要求を受け付けた時に、その応答であるCreatePrintJobResponseによりプリンタ3からPC5へ既に返されている。この印刷ジョブは図18の(c)に示す印刷ジョブ145である。管理番号が2、3のwprt:JobIdの値1002、1003は、プリンタ3がPC1、PC2から発行された要求を受け付けていないので、PC1、PC2へは未だ返されていない。これらの値は、プリンタ3が、管理番号が1の印刷ジョブ要求の印刷処理を終了した後、PC1、PC2から発行された要求を受け付ける時に備えて予約されている。
ans:EventControl欄には、図8に示すWSDのGetPrinterElementsResponse内の<ans:EventControl>要素802にセットされる値が保存されている。Status欄には、印刷ジョブ要求のプリンタ3における処理状況が保存されている。ここでは、プリンタ3がPC5から発行された印刷ジョブ要求を受信し、管理番号1として受け付けて処理している状態(Processing)を示す。また、プリンタ3が、PC1、PC2から発行された印刷ジョブ要求を受信し、管理番号が2、3としてそれぞれ印刷キューデータベース124に登録したものの、受け付けずに処理していない状態(Not Accepted)も示している。
図10の(c)は、複数の印刷ジョブを同時に受け付けて処理することができず、1つの印刷ジョブだけを受け付けて処理することができるようなプリンタ3で、受信した印刷ジョブ要求を管理する印刷キューデータベースを表す図である。印刷キューデータベースである。尚、図10の(b)で説明した内容に関しては、その説明を省略する。
図10の(b)でプリンタ3が処理していた管理番号が1の印刷ジョブ要求の印刷が終了すると、図10の(c)に示すような印刷キューデータベース124の状態に移行する。そして、プリンタ3が、PC1、PC2から発行された印刷ジョブ要求を受信し、それぞれ管理番号が1、2の印刷ジョブ要求として印刷キューデータベース124に再登録した状態を示す。また、プリンタ3が、これらの印刷ジョブ要求の内、管理番号が1の印刷ジョブ要求を受け付けて処理している状態(Processing)と、管理番号が2の印刷ジョブ要求を受け付けずに処理していない状態(Not Accepted)も示している。管理番号が1の印刷ジョブは、図18の(a)に示す印刷ジョブ144である。
図5は従来の印刷時におけるコーリングシーケンスを表す図である。今、プリンタ3は複数の印刷ジョブを受け付けることができず、1つの印刷ジョブだけを受け付けることができる、と仮定する。図5において、ユーザがアプリケーション30から印刷を開始すると(S501)、OSはスプーラ40のStartPrintJob()関数をコールする(S502)。この関数内において、スプーラ40はランゲージモニタ36のLM_StartDocPort()関数をコールする(S504)。この関数内において、ランゲージモニタ36はポートモニタ37のPM_StartDocPort()関数をコールする(S506)。この関数内において、ポートモニタ37は必要に応じて適当な処理を行い(S507)、戻り値pmRetに処理の結果を代入して、この関数を終了し、呼び出し元に戻る(S508)。
通常、正常に処理された場合は戻り値pmRetにTRUEが代入され、それ以外の場合は戻り値pmRetにFALSEが代入される。ランゲージモニタ36は、PM_StartDocPort()関数の戻り値をlmRetに代入し(S505)、LM_StartDocPort()関数を終了し、呼び出し元に戻る(S509)。
スプーラ40は、このLM_StartDocPort()関数の戻り値をspRetに代入する(S503)。ここで、spRetがTRUEではない(FALSEである)場合(S510)、スプーラ40は再びランゲージモニタ36のLM_StartDocPort()関数をコールする(S504)。一方、spRetがTRUEの場合、スプーラ40はランゲージモニタ36のLM_WritePort()関数をコールする(S512)。この関数内において、ランゲージモニタ36はポートモニタ37のPM_WritePort()関数をコールする(S514)。この関数内において、ポートモニタ37はWSDを制御するWSDAPIsのCreatePrintJob()関数をコールする。この関数内において、ポートモニタ37はWSDのプリントサービスのリクエスト(CreatePrintJobRequest)をプリンタ3に発行する。
このリクエストの中に、この印刷ジョブに関する詳細情報が含まれている。このリクエストに対してプリンタ3がレスポンス(CreatePrintJobResponse)又はFault(ServerErrorNotAcceptingJobs)をポートモニタ37に返す(S516)。プリンタ3が印刷ジョブを受け付けることができ、その印刷ジョブを受け付けた場合、プリンタ3はレスポンスをポートモニタ37に返す。しかし、プリンタ3が印刷ジョブを受け付けることができない場合、プリンタ3はFaultをポートモニタ37に返す。
ポートモニタ37がプリンタ3からCreatePrintJob()関数の戻り値を受け取るとpmRetに代入し(S515)、PM_WritePort()関数を終了して呼び出し元に戻る(S517)。そして、ランゲージモニタ36がpmRetを受け取ると、PM_WritePort()関数の戻り値をlmRetに代入し(S513)、LM_WritePort()関数を終了して呼び出し元に戻る(S518)。
スプーラ40は、このLM_WritePort()関数の戻り値をspRetに代入する(S511)。ここで、spRetがTRUEではない(FALSEである)場合(S519)、スプーラ40は再びランゲージモニタ36のLM_WritePort()関数をコールする(S512)。一方、spRetがTRUEの場合、スプーラ40は引き続き印刷データの送信処理を行う。この送信処理は、図7を用いて更に後述する。
最後に、スプーラ40はランゲージモニタ36のLM_EndDocPort()関数をコールする(S521)。この関数内において、ランゲージモニタ36はポートモニタ37のPM_EndDocPort()関数をコールする(S523)。この関数内において、ポートモニタ37は印刷が終了したことを表すイベント(JobEndStateEvent)通知待ちプロセスを起動する(S524)。
ポートモニタ37は、必要に応じて適当な処理を行い(S525)、その戻り値pmRetに処理の結果を代入し、この関数を終了し、呼び出し元に戻る(S526)。通常、正常に処理された場合は戻り値にTRUEが代入され、それ以外の場合は戻り値にFALSEが代入される。ランゲージモニタ36は、PM_EndDocPort()関数の戻り値をlmRetに代入し(S522)、LM_EndDocPort()関数を終了して呼び出し元に戻る(S527)。
スプーラ40は、このLM_EndDocPort()関数の戻り値をspRetに代入し(S520)、StartPrintJob()関数を終了し、呼び出し元に戻る(S528)。ポートモニタ37が上述のイベント通知待ちプロセスにおいて、プリンタ3からそのイベントの通知を受信すると、通知された印刷が終了した印刷ジョブをプリンタキュー32から削除する。
図10の(a)及び(c)のケースにおいて、プリンタ3がPC1から発行された印刷ジョブ要求に対して印刷処理を実行すると、プリンタキューには、図18の(a)に示すような印刷ジョブ144が「Printing」のステータスで表示される。その後、プリンタ3は、印刷が終了した時にPC1に対して印刷終了イベントを通知する。PC1内のポートモニタ37は、このイベントの通知待ちプロセスにおいて、このイベントを受信すると、印刷ジョブ144をPC1内のプリンタキューから削除する。その結果、図18の(b)に示すように、PC1内のプリンタキューから印刷ジョブ144が削除されて、表示されなくなる。
また、図10の(a)及び(b)のケースにおいても、プリンタ3はPC5から発行された印刷ジョブ要求に対して印刷処理を受け付けて処理することができる。そして、その印刷ジョブを実行すると、PC5内のプリンタキュー32には、図18の(c)に示すような印刷ジョブ145が「Printing」のステータスで表示される。
しかしながら、プリンタ3は、印刷が終了した時にPC5に対して印刷終了のイベントを通知することができない。その結果、PC5内のポートモニタ37は、このイベントの通知待ちプロセスにおいて、PC5から発行された印刷ジョブ145の印刷が終了したことを表すイベントを一切受信することができない。その結果、図18の(d)に示すように、PC5内のプリンタキュー32に印刷ジョブ145が「Sent to printer」のステータスで残ってしまう。
即ち、プリンタ3がこのイベントを通知することができないPC5のようなPCからの印刷ジョブが、印刷が終了しているにもかかわらず「Sent to printer」のステータスでプリンタキューに残ってしまう。
図6、図11は印刷時のコーリングシーケンスを表す図である。これらの図は本発明の特徴を最もよく表す図の内の1つである。今、プリンタ3は、1つの印刷ジョブ要求だけを受け付けて、その印刷ジョブを処理して印刷を実行することができ、図10の(a)に示すようにPC1とPC2の2台のPCにだけイベントを通知できる、というような廉価版のプリンタである、と仮定する。
図6において、ユーザがアプリケーション30から印刷を開始すると(S601)、OSはスプーラ40のStartPrintJob()関数をコールする(S602)。この関数内において、スプーラ40はランゲージモニタ36のLM_StartDocPort()関数をコールする(S604)。この関数内において、ランゲージモニタ36はフラグlmDeleteJobにFALSEを代入して初期化する(S605)。このフラグは、ランゲージモニタ36内で使用されるものであり、プリンタ3がその印刷ジョブを発行したPCに対してその印刷ジョブが終了したことを表すイベントを通知することができない場合に、TRUEがセットされる。それ以外の場合にFALSEがセットされる。ランゲージモニタ36はlmJobIdに0を代入して初期化する(S606)。その後、ランゲージモニタ36は図5のS505〜S509と同じ処理を行う。
スプーラ40は、S509と同じ処理で返されたLM_StartDocPort()関数の戻り値をspRetに代入する(S603)。スプーラ40は、spRetがTRUEではない(FALSEである)場合(S607)、ランゲージモニタ36のLM_StartDocPort()関数をコールする。一方、このspRetがTRUEの場合、図11のS1101へ進む。図11に示す印刷ジョブ要求の発行と印刷ジョブ情報の取得等に関して後述する。
最後に、スプーラ40はランゲージモニタ36のLM_EndDocPort()関数をコールする(S609)。この関数内において、ランゲージモニタ36は、引数にwprt:PrinterDescriptionをセットし、WSDを制御するWSDAPIsのGetPrinterElements()関数をコールする。この関数内において、ポートモニタ37はWSDのプリントサービスのリクエスト(GetPrinterElementsRequest)をプリンタ3に発行する。このリクエストに対してプリンタ3がレスポンス(GetPrinterElementsResponse)をポートモニタ37に返す(S611)。ここでポートモニタ37がレスポンスを受け取ると、GetPrinterElements()関数の戻り値にTRUEを代入し、呼び出し元に戻る(S610)。
また、ポートモニタ37がプリンタ3に対してリクエストを発行してからある一定時間の間にレスポンスを受け取らなかった場合、GetPrinterElements()関数の戻り値にFALSEを代入し、呼び出し元に戻る(S610)。
ランゲージモニタ36はGetPrinterElements()関数の戻り値をlmRetに代入する。尚、ここでは、GetPrinterElements()関数の戻り値としてFALSEが返されるようなエラーケースの説明は省略する。ポートモニタ37が発行するリクエストと、リクエストに対してプリンタ3が返信するレスポンスの詳細に関しては図8で説明する。
ランゲージモニタ36は、S610のGetPrinterElements()関数の引数として渡されたレスポンス内の<wprt:DeviceId>要素804にセットされている値を取得し、プリンタ3の状態を判定を行う。その中に含まれるINFO:にセットされている値が、オンラインでスタンバイ状態を表す「000」、即ち<wprt:DeviceId>要素804にセットされている値の中に「INFO:000」が含まれているか否かを判定する(S612)。ここで、プリンタ3がオンラインでスタンバイ状態であるということは、印刷が終了したしたことを意味する。S612において、ランゲージモニタ36が、<wprt:DeviceId>要素804にセットされている値の中に「INFO:000」が含まれていると判定した場合、図5のS522〜S526と同じ処理を行う。しかし、含まれていないと判定した場合にはS610に戻る。
このとき、ランゲージモニタ36はS522と同じ処理により、PM_EndDocPort()関数の戻り値をlmRetに代入する。ランゲージモニタ36は、lmDeleteJobにセットされている値を確認し、TRUEがセットされている場合(S613)、図13のステップS1304、S1306に示す印刷ジョブの削除処理を行う(S614)。例えば、図13のS1306で、ランゲージモニタ36がこの印刷ジョブを削除した場合、「Sent to printer」のステータスの印刷ジョブ(図18の(c)の印刷ジョブ145)がプリンタキュー32から削除される(図18の(e))。ランゲージモニタ36はlmDeleteJobにFALSEを代入して初期化する(S615)。ランゲージモニタ36はlmJobIdに0を代入して初期化する(S616)。
ランゲージモニタ36は、lmRetの値をLM_EndDocPort()関数の戻り値として返し、LM_EndDocPort()関数を終了し、呼び出し元に戻る(S617)。S609〜S617に示すLM_EndDocPort()関数の処理の詳細に関しては、図13で説明する。スプーラ40は、このLM_EndDocPort()関数の戻り値をspRetに代入し(S608)、StartPrintJob()関数を終了し、呼び出し元に戻る(S618)。
図11において、スプーラ40はランゲージモニタ36のLM_WritePort()関数をコールする(S1102)。この関数内において(S1103)、ランゲージモニタ36はポートモニタ37のPM_WritePort()関数をコールする(S1104)。この関数内において(S1105)、ポートモニタ37はWSDを制御するWSDAPIsのCreatePrintJob()関数をコールする(S1106)。この関数内において、PC(PC5)は、印刷ジョブ要求、即ちWSDのプリントサービスのリクエスト(CreatePrintJobRequest)をプリンタ3に発行する。このリクエストの中に、この印刷ジョブに関する詳細情報が含まれている。このリクエストに対してプリンタ3はレスポンス(CreatePrintJobResponse)又はFault(ServerErrorNotAcceptingJobs)をポートモニタ37に返す(S1107)。
プリンタ3が印刷ジョブ要求を受け付け、実行することができる状態の時に、その印刷ジョブ要求を受け付けた場合、プリンタ3はその印刷ジョブ要求を発行したポートモニタ37に対してレスポンスを返す。また、プリンタ3が印刷ジョブ要求を受け付けることができない状態の時に、印刷ジョブ要求を受け付けない場合、プリンタ3はその印刷ジョブ要求を発行したポートモニタ37に対してFaultを返す。
ポートモニタ37がレスポンスを受け取ると、CreatePrintJob()関数の戻り値にTRUEを代入し、呼び出し元に戻る(S1106)。このとき、プリンタ3はレスポンス内の<wprt:JobId>要素に、図10の(b)、(c)のwprt:JobId欄に保存されている値をセットしておく。一方、ポートモニタ37がFaultを受け取ると、CreatePrintJob()関数の戻り値にFALSEを代し、呼び出し元に戻る(S1106)。ポートモニタ37は、戻り値pmRetにCreatePrintJob()関数の戻り値を代入し(S1106)、PM_WritePort()関数を終了し、呼び出し元に戻る(S1108)。
ランゲージモニタ36は、PM_WritePort()関数の戻り値をlmRetに代入する(S1104)。ランゲージモニタ36は、lmRetの値を確認し(S1109)、TRUEの場合S1110へ進み、TRUEではない(FALSE)場合S1117へ進む。このS1110では、ランゲージモニタ36は、引数にwprt:PrinterDescriptionをセットして、WSDを制御するWSDAPIsのGetPrinterElements()関数をコールする。この関数内において、WSDのプリントサービスのリクエスト(GetPrinterElementsRequest)をプリンタ3に発行する。このリクエストに対してプリンタ3はレスポンス(GetPrinterElementsResponse)をポートモニタ37に返す(S1111)。
ポートモニタ37がレスポンスを受け取ると、GetPrinterElements()関数の戻り値にTRUEを代入し、呼び出し元に戻る(S1110)。また、ポートモニタ37がプリンタ3に対してリクエストを発行した後、一定時間の間にレスポンスを受け取らなかった場合、GetPrinterElements()関数の戻り値にFALSEを代入し、呼び出し元に戻る(S1110)。S1110において、ランゲージモニタ36はGetPrinterElements()関数の戻り値をlmRetに代入する。尚、ここでは、GetPrinterElements()関数の戻り値としてFALSEが返されるようなエラーケースの説明は省略する。また、S1110でポートモニタ37が発行するリクエストと、リクエストに対してプリンタ3が返信するレスポンスの詳細に関しては図8で説明する。
ランゲージモニタ36は、S1110のGetPrinterElements()関数の引数として渡されたレスポンス内の<ans:EventControl>要素802の値を取得し「false」と比較する(S1112)。S1112において、ランゲージモニタ36が「false」であると判定した場合、lmDeleteJobにTRUEを代入する(S1113)。このとき、<wprt:DeviceId>要素804にセットされている値は次の値であり、プリンタ3が印刷処理中(Processing)であることを表す「INFO:001」の状態であることがわかる。「MFG:ABC;CMD:ABCCommand;MDL:Kmmn;CLS:PRINTER;DES:ABC Kmmn;VER:1.00;INFO:001;」
ランゲージモニタ36は、WSDを制御するWSDAPIsのGetActiveJobs関数をコールする(S1114)。この関数内において、ポートモニタ37はWSDのプリントサービスのリクエスト(GetActiveJobsRequest)をプリンタ3に発行する。このリクエストに対してプリンタ3はレスポンス(GetActiveJobsResponse)をポートモニタ37に返す(S1115)。ポートモニタ37がレスポンスを受け取ると、GetActiveJobs関数の戻り値にTRUEを代入し、呼び出し元に戻る(S1114)。また、ポートモニタ37がプリンタ3に対してリクエストを発行してからある一定時間の間に、レスポンスを受け取らなかった場合、GetActiveJobs関数の戻り値にFALSEを代入し、呼び出し元に戻る(S1114)。S1114において、ランゲージモニタ36はGetActiveJobs関数の戻り値をlmRetに代入する。
尚、ここでは、GetActiveJobs関数の戻り値としてFALSEが返されるようなエラーケースの説明は省略する。S1114でポートモニタ37が発行するリクエストと、それに対してプリンタ3が返すレスポンスの詳細に関しては図14で説明する。
ランゲージモニタ36は、S1114のGetActiveJobs関数の引数として渡されたレスポンス内の<wprt:JobId>要素1402の値を取得し、lmJobIdに代入する(S1116)。ランゲージモニタ36はLM_WritePort()関数を終了し、呼び出し元に戻る(S1117)。このとき、このLM_WritePort()関数の戻り値として、lmRetの値が返される(S1117)。
スプーラ40は、このLM_WritePort()関数の戻り値をspRetに代入する(S1102)。spRetがTRUEではない(FALSE)場合(S1118)、S1102に戻り、スプーラ40はランゲージモニタ36のLM_WritePort()関数をコールする。S1118においてspRetがTRUEの場合、スプーラ40は引き続き図7に示す印刷データの送信処理を行う。その後、ランゲージモニタ36が図6のS609〜S617の処理を行い、スプーラ40が図6のS618の処理を行うことで、印刷が終了する。
このように、図10の(a)及び(b)のケースにおいて、図18の(e)に示すように、印刷が終了した印刷ジョブ145をPC5内のプリンタキュー32から自動的に削除することができ、ユーザの操作性に優れる。
図7は印刷時のコーリングシーケンスを表す図である。図5のS519又は図11のS1118において、spRetがTRUEの場合、スプーラ40はランゲージモニタ36のLM_WritePort()関数をコールする(S702)。この関数内において、ランゲージモニタ36はポートモニタ37のPM_WritePort()関数をコールする(S704)。この関数内において、ポートモニタ37はWSDを制御するWSDAPIsのSendDocument()関数をコールする。この関数内において、PCはWSDのプリントサービスのリクエスト(SendDocumentRequest)をプリンタ3に発行する。その際に、MTOM(Message Transmission Optimization Mechanism)メッセージエンコーディングを使う。そして印刷制御コマンドで構成された印刷データを、SOAPメッセージを使用して未処理のバイトとしてプリンタ3に送信する。
プリンタ3は、このリクエストに対してレスポンス(SendDocumentResponse)をポートモニタ37に返す(S706)。ポートモニタ37がこのレスポンスを受け取り、全ての印刷データをプリンタ3に送信し終わると、SendDocument()関数の戻り値にTRUEを代入し、呼び出し元に戻る(S705)。ポートモニタ37がリクエストを発行した時、或いはレスポンス受け取った時に、何らかのエラーが発生した場合、SendDocument()関数の戻り値にFALSEを代入し、呼び出し元に戻る(S705)。ポートモニタ37は、戻り値pmRetにSendDocument()関数の戻り値を代入し(S705)、PM_WritePort()関数を終了し、呼び出し元に戻る(S707)。
ランゲージモニタ36は、PM_WritePort()関数の戻り値をlmRetに代入し(S703)、LM_WritePort()関数を終了し、呼び出し元に戻る(S708)。スプーラ40は、このLM_WritePort()関数の戻り値をspRetに代入する(S701)。ここで、spRetがTRUEではない(FALSE)場合(S709)、S701に戻り、スプーラ40はランゲージモニタ36のLM_WritePort()関数をコールする。一方、spRetがTRUEの場合、図5のS520又は図6のS608へ進む。
図19は、CreatePrintJobの内容を表す図、図8、図17はGetPrinterElementsの内容を表す図である。図14はGetActiveJobsの内容を表す図、図22はJobEndStateEventの内容を表す図である。CreatePrintJobオペレーションは、印刷ジョブの開始要求である。GetPrinterElementsオペレーションは、通常プリンタに関する情報を取得するために利用される。GetActiveJobsオペレーションは、通常プリンタ内で処理中の印刷ジョブに関する情報を取得するために利用される。JobEndStateEventは、印刷ジョブの終了を表す印刷終了イベントである。CreatePrintJob、GetPrinterElements、GetActiveJobsの一般的な内容に関しては、WSDのプリントサービスDefinition Version 1.0で定義されているので、説明は省略する。
図19はCreatePrintJobの内容を表す図であり、(a)はCreatePrintJobRequest、(b)はCreatePrintJobResponseをそれぞれ表す。
図19の(a)のリクエストは、PC5がプリンタ3に発行するものの一例である。図示するように、リクエストには、WSDのプリントサービスの名前空間を名前空間名wprtと定義する記述1905が含まれる。名前空間名wprtの有効範囲内は、WSDのプリントサービスDefinition Version 1.0で定義されているパブリック情報である。これ以降の図においても、名前空間名wprtは同様な取り扱いとなり、名前空間名wprtの有効範囲内はWSDのプリントサービスDefinition Version 1.0で定義されているパブリック情報を表す。
<wprt:JobDescription>要素1901はパブリック情報であり、この中に印刷ジョブに関する情報が含まれている。<wprt:JobName>要素1902はパブリック情報であり、印刷ジョブ名がセットされる。この例では、図18の(c)に示す印刷ジョブ145のDocument Nameと同じ「Photo2」という印刷ジョブ名がセットされている状態を表す。
<wprt:JobOriginatingUserName>要素1903はパブリック情報であり、この印刷ジョブを発行したユーザ名がセットされる。この例では、図18の(c)に示す印刷ジョブ145のOwnerと同じ「Natsu」というユーザ名がセットされている状態を表す。
図19(b)のレスポンスは、プリンタ3がPC5に返すものの一例である。ここで、<wprt:JobId>要素1904はパブリック情報であり、PC5からリクエストされた印刷ジョブを識別するためにプリンタ3が割り当てたジョブIDがセットされる。この例では、「1001」(図10の(b)の管理番号が1の印刷ジョブ要求のwprt:JobId欄)というジョブIDがセットされている状態を表す。
図8はGetPrinterElementsの内容を表す図である。図8の(a)はGetPrinterElementsRequest、(b)はGetPrinterElementsResponseをそれぞれ表す。図8は本発明の特徴を最もよく表す図の内の1つである。
図8の(a)に示すリクエストは、PC5がプリンタ3に発行するものの一例である。このリクエストの<wprt:Name>要素801はパブリック情報であり、その値としてwprt:PrinterDescriptionがセットされている。
図8の(b)に示すレスポンスは、プリンタ3がPC5に返すものの一例である。プリンタ3は、wprt:PrinterDescriptionがセットされた<wprt:Name>要素801を含むリクエストを受け取ると、このレスポンスでwprt:PrinterDescriptionをPC5に返す。
このレスポンスには、ABC社のWSDを利用したプリントサービスの名前空間を名前空間名ansと定義している記述806が含まれる。名前空間名ansの有効範囲内は、ABC社のWSDを利用したプリントサービスで定義されているプライベート情報である。これ以降の図においても、名前空間名ansは同様な取り扱いとなり、名前空間名ansの有効範囲内は、ABC社のWSDを利用したプリントサービスで定義されているプライベート情報を表す。
<wprt:ElementData>要素803はパブリック情報であり、Name属性としてパブリック情報のwprt:PrinterDescriptionがセットされている。これは、このレスポンスが<wprt:Name>要素801で指定されたwprt:PrinterDescriptionを含むことを表す。<wprt:PrinterDescription>要素805はパブリック情報であり、プリンタ3に搭載されている機能等に関する情報がこの中に含まれている。
<wprt:DeviceId>要素804はパブリック情報であり、IEEE 1284-2000ノDevice IDで定義されたデータ(文字列)がセットされている。これはプリンタ3のDevice IDを表す。この例では、「MFG:ABC;CMD:ABCCommand;MDL:Kmmn;CLS:PRINTER;DES:ABC Kmmn;VER:1.00;INFO:001;」というDevice IDがセットされている状態を表す。このDevice IDの中にプリンタ3の状態を表す情報INFO:xxx(xxxは以下に記す何れかの値)が含まれており、以下に示す状態を表す。
INFO:
000 オンラインでスタンバイ状態
001 印刷処理中(Processing)
<ans:EventControl>要素802はプライベート情報であり、プリンタ3がPCに対してWSDのイベントを通知することができるか否かを表す。プリンタ3がそのPCに対してWSDのイベントを通知することができる場合は「true」が、通知することができない場合は「false」が、要素802にセットされる。この例では、「false」がセットされており、プリンタ3がそのPCに対してWSDのイベントを通知することができない状態を表す。
<ans:MultipleJobsControl>要素807はプライベート情報であり、プリンタ3が1つの印刷ジョブだけを受け付けて処理可能か、複数の印刷ジョブ要求を同時に受け付けて処理可能かを表す。プリンタ3が1つの印刷ジョブだけを受け付けて処理可能なプリンタである場合は「false」が、複数の印刷ジョブ要求を同時に受け付けて処理可能なプリンタである場合は「true」が要素807にセットされる。この例では、「false」がセットされており、プリンタ3が1つの印刷ジョブだけを受け付けて処理可能なプリンタであることを表す。
図14はGetActiveJobsの内容を表す図であり、(a)はGetActiveJobsRequest、(b)はGetActiveJobsResponseをそれぞれ表す。ここで、図14の(a)に示すリクエストは、PC5がプリンタ3に発行するものの一例である。図14の(b)に示すレスポンスは、プリンタ3がPC5に返すものの一例である。
<wprt:ActiveJobs>要素1403はパブリック情報であり、プリンタ3が処理中の全ての印刷ジョブに関する情報を表す。<wprt:JobSummary>要素1401はパブリック情報であり、プリンタ3が処理中の各印刷ジョブに関する情報を印刷ジョブ単位で表す。
<wprt:ActiveJobs>要素1403の中に<wprt:JobSummary>要素が0〜複数含まれる。図18の(c)に示す印刷ジョブ145(図10の(b)の管理番号1の印刷ジョブ)を表す<wprt:JobSummary>要素1401が<wprt:ActiveJobs>要素1403の中に1つだけ含まれているケースを表している。印刷が終了した印刷ジョブは<wprt:ActiveJobs>要素1403の中には含まれない。
従って、次の場合には、PCからのリクエストに対するプリンタ3からのレスポンスの中の<wprt:ActiveJobs>要素1403の中には印刷ジョブ145の<wprt:JobSummary>要素1401は含まれない。つまり、図10の(b)に示す状態から印刷ジョブ145の印刷が終了した状態に変わった後、その後、次の印刷ジョブ(図18の(a)に示す印刷ジョブ144)が開始されて図10の(c)に示す状態に変わった後。これにより、PC5は、GetActiveJobsオペレーションを使って印刷ジョブ145の印刷が終了したことを把握することができる。
<wprt:JobId>要素1402はパブリック情報であり、印刷ジョブのジョブIDがセットされている。このジョブIDは、この印刷ジョブを受け付けた時にプリンタ3からPC5へ返された、図19の(b)に示すCreatePrintJobResponseの<wprt:JobId>要素1904にセットされているジョブIDと同一である。ここでは、PC5から発行された、図18の(c)に示す印刷ジョブ145に対してプリンタ3が割り当てた「1001」というジョブIDがセットされている状態を表す。
<wprt:JobState>要素1404は、印刷ジョブの状態(処理状況)を表す値がセットされている。ここでは、印刷ジョブ145の図10の(b)のStatus欄に示す値がセットされている状態を表す。<wprt:JobName>要素1405はパブリック情報であり、この印刷ジョブの印刷ジョブ名がセットされる。この印刷ジョブ名は、図19の(a)に示すCreatePrintJobRequestの<wprt:JobName>要素1902にセットされている印刷ジョブ名と同一である。
<wprt:JobOriginatingUserName>要素1406はパブリック情報であり、印刷ジョブを発行したユーザ名がセットされる。このユーザ名は、図19の(a)に示すCreatePrintJobRequestの<wprt:JobOriginatingUserName>要素1903にセットされているユーザ名と同一である。
図22はJobEndStateEventの内容を表す図である。図22に示すイベントは、プリンタ3がPC1に通知するものの一例であり、図18の(a)に示す印刷ジョブ144のプリンタ3における印刷が終了し、図18の(b)に示す状態に移行した時の例を示す。
<wprt:JobEndStateEvent>要素2201はパブリック情報であり、印刷ジョブの終了を表す印刷終了イベント(JobEndStateEvent)を表す。<wprt:JobEndState>要素2202はパブリック情報であり、この印刷終了イベントの詳細情報を表す。
<wprt:JobId>要素2203はパブリック情報であり、印刷ジョブのジョブIDがセットされている。このジョブIDは、この印刷ジョブを受け付けた時にプリンタ3からPC1へ返されたレスポンス内の<wprt:JobId>要素(不図示)にセットされているジョブIDと同一である。この例では、PC1から発行された、図18の(a)に示す印刷ジョブ145に対してプリンタ3が割り当てた「1002」というジョブID(図10の(c)の管理番号1の印刷ジョブ要求のwprt:JobId欄)がセットされている状態を表す。
<wprt:JobCompletedState>要素2204はパブリック情報であり、印刷ジョブが完了した時の状態を表す。この例では印刷ジョブが正常に完了したことを表す「Completed」がセットされている状態を表す。<wprt:JobCompletedStateReasons>要素2205はパブリック情報であり、印刷ジョブが完了した時の状態の理由が、この要素の中に1つ又は複数個含まれる。
<wprt:JobCompletedStateReason>要素2206はパブリック情報であり、印刷ジョブが完了した時の状態の理由を表す。この例では、印刷ジョブが正常に完了したことを表す「JobCompletedSuccessfully」がセットされている状態を表す。<wprt:JobName>要素2207はパブリック情報であり、印刷ジョブの印刷ジョブ名がセットされる。この印刷ジョブ名は、PC1から発行されたリクエスト内の<wprt:JobName>要素(不図示)にセットされている印刷ジョブ名と同一である。
<wprt:JobOriginatingUserName>要素2208はパブリック情報であり、印刷ジョブを発行したユーザ名がセットされる。このユーザ名は、PC1から発行されたリクエスト内の<wprt:JobOriginatingUserName>要素(不図示)にセットされているユーザ名と同一である。
図18はプリンタキューを表す図である。図18において、(a)と(b)はPC1内のプリンタキュー、(c)〜(e)はPC5内のプリンタキューを表す図である。これらのプリンタキューは、ユーザ操作により左上部の「Printer」メニューから「Properties」を選択し、このプリンタキューのプロパティを開くことができる。そして、このプロパティ内の「Advanced」シートの中に「印刷後にドキュメントを残す」機能を選択する手段を備えており(不図示)、ユーザの操作によりこの機能のオン/オフを切り換えることができる。尚、この機能のデフォルトの設定値はオフである。
図18の(a)において、印刷ジョブ144はPC1がプリンタ3に対して発行したものである。印刷ジョブ144のステータス(Status)が「Printing」と表示されているので、印刷ジョブ144がプリンタ3で印刷中であることがわかる。
図18の(b)は、図18の(a)で印刷中であった印刷ジョブ144の印刷が、プリンタ3において終了した後の状態を表す。この図から、印刷が終了した印刷ジョブ144が、PC1内のプリンタキューから削除され、表示されていないことがわかる。尚、PC1内のプリンタキューの状態が図18の(a)から(b)へ変化する過程において、次のように処理される。PC1が印刷ジョブ144の全ての印字データをプリンタ3に転送し終えた時点で、PC1内のプリンタキューは印刷ジョブ144のステータス(Status)が「Sent to printer」に変わる。その後、プリンタ3において、印刷が終了した時点で、印刷ジョブ144がPC1内のプリンタキューから削除される。
図18の(c)において、印刷ジョブ145はPC5がプリンタ3に対して発行したものである。印刷ジョブ145のステータス(Status)が「Printing」と表示されているので、印刷ジョブ145がプリンタ3で印刷中であることがわかる。
図18の(d)は、図18の(c)で印刷中であった印刷ジョブ145の印刷が、プリンタ3において終了した後の状態を表す。この図では、PC5が印刷ジョブ145の全ての印字データをプリンタ3に転送し終えており、かつ、プリンタ3で印刷ジョブ145の印刷が終了している状態である。しかしながら、印刷ジョブ145が「Sent to printer」のステータス(Status)の状態でPC5内のプリンタキュー32に残ってしまっている。これが、本発明で解決しようとしている従来例の問題点である。
図18の(e)は、(d)の状態ではPC5内のプリンタキュー32に残ってしまっていた印刷ジョブ145がプリンタキュー32から削除され、表示されていない状態を表す。図18の(e)では、本発明が従来例の問題点を解決し、ユーザの操作性に優れる例を表している。
図12はランゲージモニタ36におけるLM_WritePort()関数の処理を表すフローチャートである。図12は本発明の特徴を最もよく表す図の内の1つである。図12のフローに係るプログラムは、HDD202に記憶されており、RAM201に読み出され、CPU204により実行される。
図11のS1102において、スプーラ40がランゲージモニタ36のLM_WritePort()関数をコールすると、図12において、ランゲージモニタ36がLM_WritePort()関数の処理を開始する(S1201)。ランゲージモニタ36は、ポートモニタ37のPM_WritePort()関数をコールし、その関数の戻り値をlmRetに代入する(S1202)。ランゲージモニタ36は、S1203でlmRetの値を確認し、TRUEの場合はS1204へ進み、TRUEではない(FALSEである)場合はS1211へ進む。
S1204において、ランゲージモニタ36は、引数にwprt:PrinterDescriptionをセットし、WSDを制御するWSDAPIsのGetPrinterElements()関数をコールする。この関数内において、PC5はWSDのプリントサービスのリクエスト(GetPrinterElementsRequest)をプリンタ3に発行する(S1204、図11のS1110)。このリクエストに対してプリンタ3はレスポンス(GetPrinterElementsResponse)をPC5に返す(S1204、図11のS1111)。PC5がこのレスポンスを受け取ると、GetPrinterElements()関数の戻り値にTRUEが代入され、呼び出し元であるランゲージモニタ36に戻る(S1204、図11のS1110)。
また、PC5がプリンタ3に対してリクエストを発行後、一定の時間内にレスポンスを受け取らなかった場合、GetPrinterElements()関数の戻り値にFALSEを代入する。そして、呼び出し元であるランゲージモニタ36に戻る(S1204、図11のS1110)。ランゲージモニタ36はGetPrinterElements()関数の戻り値をlmRetに代入する(S1204、図11のS1110)。
尚、ここでは、GetPrinterElements()関数の戻り値としてFALSEが返されるようなエラーケースの説明は省略する。また、S1204でPC5が発行するリクエストと、リクエストに対してプリンタ3が返信するレスポンスの詳細に関しては図8に示す。
ランゲージモニタ36は、GetPrinterElements()関数の引数として渡されたレスポンス内の<ans:EventControl>要素802にセットされている値を取得する(S1205)。ランゲージモニタ36は、S1206で、この値が「false」であるか否かを確認し、「false」である場合はS1207へ進み、「false」ではない(「true」である)場合はS1208へ進む。
S1207において、ランゲージモニタ36は、lmDeleteJobにTRUEを代入し、S1208へ進む。S1208において、ランゲージモニタ36は、WSDを制御するWSDAPIsのGetActiveJobs関数をコールする(図11のS1114)。この関数内において、PC5はWSDのプリントサービスのリクエスト(GetActiveJobsRequest)をプリンタ3に発行する(S1208、図11のS1114)。
このリクエストに対してプリンタ3がレスポンス(GetActiveJobsResponse)をPC5に返す(S1208、図11のS1115)。PC5がこのレスポンスを受け取ると、GetActiveJobs関数の戻り値にTRUEを代入し、呼び出し元に戻る(S1208、図11のS1114)。
また、PC5がプリンタ3に対してリクエストを発行後、一定の時間内にレスポンスを受け取らなかった場合、GetActiveJobs関数の戻り値にFALSEを代入し、呼び出し元に戻る(S1208、図11のS1114)。ランゲージモニタ36はGetActiveJobs関数の戻り値をlmRetに代入する(S1208、図11のS1114)。
尚、ここでは、GetActiveJobs関数の戻り値としてFALSEが返されるようなエラーケースの説明は省略する。S1114でPC5が発行するリクエストと、リクエストに対してプリンタ3が返信するレスポンスの詳細に関しては図14に示す。
ランゲージモニタ36は、GetActiveJobs関数の引数として渡されたGetActiveJobsResponse内の<wprt:JobId>要素1402にセットされている値を取得する(S1209、図11のS1116)。そして、lmJobIdに代入し(S1210、図11のS1116)、S1211へ進む。S1211において、ランゲージモニタ36は、LM_WritePort()関数の戻り値として、lmRetをスプーラ40に返し、LM_WritePort()関数の処理を終了し、呼び出し元であるスプーラ40に戻る。
図13はランゲージモニタ36におけるLM_EndDocPort()関数の処理を表すフローチャートである。図13は本発明の特徴を最もよく表す図の内の1つである。図13のフローに係るプログラムは、HDD202に記憶されており、RAM201に読み出され、CPU204により実行される。
PCがプリンタ3に対して印刷ジョブを発行して印刷を行うケースにおいて、PCがその印刷ジョブの全ての印刷データをプリンタ3に送信し終わった時、スプーラ40がLM_EndDocPort()関数をコールする。そして、ランゲージモニタ36がこのLM_EndDocPort()関数の処理を開始する。
図6のS608で、スプーラ40がLM_EndDocPort()関数をコールすると、ランゲージモニタ36がLM_EndDocPort()関数の処理を開始する(S1301)。ランゲージモニタ36は、引数にwprt:PrinterDescriptionをセットし、WSDを制御するWSDAPIsのGetPrinterElements()関数をコールする(S1302)。この関数内において、PC5はWSDのプリントサービスのリクエスト(GetPrinterElementsRequest)をプリンタ3に発行する(S1302、図6のS610)。
このリクエストに対して、プリンタ3はレスポンス(GetPrinterElementsResponse)をPC5に返す(S1302、図6のS611)。PC5がこのレスポンスを受け取ると、GetPrinterElements()関数の戻り値にTRUEを代入し、呼び出し元であるランゲージモニタ36に戻る(S1302、図6のS610)。
PC5がプリンタ3に対してリクエストを発行後、一定の時間内に、レスポンスを受け取らなかった場合、GetPrinterElements()関数の戻り値にFALSEを代入する。そして、呼び出し元であるランゲージモニタ36に戻る(S1302、図6のS610)。ランゲージモニタ36はGetPrinterElements()関数の戻り値をlmRetに代入する(S1302、図6のS610)。
尚、ここでは、GetPrinterElements()関数の戻り値としてFALSEが返されるようなエラーケースの説明は省略する。また、S1302でPC5が発行するリクエストと、リクエストに対してプリンタ3が返信するレスポンスの詳細に関しては図8に示す。
ランゲージモニタ36は、S1302のGetPrinterElements()関数の引数として渡されたレスポンス内の<wprt:DeviceId>要素804にセットされている値を取得する。そして、その中に含まれるプリンタ3の状態を表す情報INFO:xxx(xxxは「000」、「001」の何れかの値)を取得する(S1311)。ランゲージモニタ36は、INFO:xxxを確認し、プリンタ3がオンラインでスタンバイ状態を表す「INFO:000」であると判定した場合はS1307へ進む。また、「INFO:000」ではない(「INFO:001」である)と判定した場合はS1302に戻る。ここで、プリンタ3がオンラインでスタンバイ状態であるということは、印刷が終了したしたことを意味する。
つまり、ランゲージモニタ36は、S1302、S1311、S1303の一連の処理を繰り返すことで、プリンタ3における印刷が終了したか否かを見とどけ、印刷が終了した後に、S1307へ進む。
S1307において、ランゲージモニタ36は、ポートモニタ37のPM_EndDocPort()関数をコールし、その関数の戻り値をlmRetに代入する。ランゲージモニタ36は、lmDeleteJobの値を確認し、TRUEの場合はS1304へ進み、TRUEではない(FALSEである)場合はステップS1309へ進む。S1304において、ランゲージモニタ36は、プリンタキュー32の「印刷後にドキュメントを残す」機能の設定値を確認し、オンの場合はS1309へ進み、オフの場合はS1306へ進む。
S1306において、ランゲージモニタ36は、その印刷ジョブをプリンタキュー32から削除する。このとき、例えば、OSが提供しているSetJob()関数を利用し、その第5引数のCommandにJOB_CONTROL_RELEASEという値をセットし、この関数をコールすることで、プリンタキュー32から印刷ジョブを削除することができる。
これは、ポートモニタ37が印刷開始時にSetJob()関数を利用し、その第5引数のCommandにJOB_CONTROL_RETAINという値をセットしてこの関数をコールしているからである。
BOOL SetJob(
_in HANDLE hPrinter,
_in DWORD JobId,
_in DWORD Level,
_in LPBYTE pJob,
_in DWORD Command
);
Command [in]: The print job operation to perform. This parameter can be one of the following values.
JOB_CONTROL_RETAIN: Keep the job in the queue after it prints.
JOB_CONTROL_RELEASE: Release the print job.
JOB_CONTROL_RESTART: Restart the print job. A job can only be restarted if it was printing.
尚、SetJob()関数を利用する際に、第1〜第4引数にセットする値に関しては、一般的な情報である。そして、Microsoft Developer Network (MSDN)のサイトに記載されている情報であるので、ここでは説明を省略する。
S1309において、ランゲージモニタ36は、lmDeleteJobにFALSEを代入して初期化し、lmJobIdに0を代入して初期化する(S1310)。ランゲージモニタ36は、LM_EndDocPort()関数の戻り値として、lmRetをスプーラ40に返し、LM_EndDocPort()関数の処理を終了し、呼び出し元であるスプーラ40に戻る(S1305)。
S1304において、プリンタキュー32の「印刷後にドキュメントを残す」機能がオンの場合、ランゲージモニタ36が印刷ジョブをプリンタキュー32から削除しないようにする。これにより、この機能が正しく動作し、印刷が終了した後もプリンタキュー32にこの印刷ジョブが残る。
このように、図10の(a)と(b)で示されるケースにおいて、プリンタ3が、印刷が終了したことを表すイベントをPC5に返すことができない場合にも、印刷が終了した印刷ジョブをプリンタキューから自動的に削除できる。従って、ユーザの操作性に優れる。
仮に、全ての印刷ジョブにおいて、ランゲージモニタがその印刷ジョブをプリンタキューから削除する処理を実装した場合に、プリンタが、印刷が終了したことを表すイベントをPCに返すことができるケースを考える。このようなケースでは、ポートモニタがJobEndStateEvent通知待ちプロセスの中で印刷が終了したその印刷ジョブをプリンタキューから削除し、またランゲージモニタもその印刷ジョブをプリンタキューから削除する。そのため、ポートモニタ又はランゲージモニタのどちらか一方で既に削除済みの印刷ジョブに対して、再度その印刷ジョブを削除しようとすることになる。その結果、プリンタキューから既に削除されている印刷ジョブを二重に削除しようとする処理が発生し、この処理によってOS内で予期せぬ誤動作をまねく恐れがある、という問題が発生する。
そこで、本実施形態では、まず図12のS1204、S1205で、ランゲージモニタ36がGetPrinterElementsオペレーションを利用して<ans:EventControl>要素802を取得する。そして、ランゲージモニタ36が、その値に応じて「false」の場合のみlmDeleteJobにTRUEを代入し、このlmDeleteにセットされた値がTRUEの時のみ、図13のS1306においてプリンタキュー32から印刷ジョブを削除する。
このように、ランゲージモニタ36が<ans:EventControl>要素802を利用して制御を行うことで、上述の問題が発生することを防止でき、OS内で誤動作することのない、安全な周辺装置制御システムを実現することができる。
この例では、図12のS1202でポートモニタ37がCreatePrintJobオペレーションを実行した後、即ち印刷ジョブ要求発行後に、S1204でランゲージモニタ36がGetPrinterElementsオペレーションを実行する。そして、<wprt:EventControl>要素802を取得する例を挙げた。ここではその理由を説明する。
ランゲージモニタ36はS1204のGetPrinterElementsオペレーションにより、図8に示すようなDevice IDも取得している。これは、CreatePrintJobオペレーションで発行された印刷ジョブに含まれる最初の印刷制御コマンドがPC5から送信された後、ランゲージモニタ36は、プリンタ3と双方向通信を行うことができるか否かを確認する。そのために、ランゲージモニタ36は、Device IDの取得を試みることで、プリンタ3から送られてくるデータを受信することができるか否かを判別する。
S1204において、ランゲージモニタ36がDevice IDを取得するためにGetPrinterElementsオペレーションを発行することは従来例から実施されていた。本実施形態では、このS1204のGetPrinterElementsオペレーションを利用し、Device IDと<wprt:EventControl>要素802を同時に取得している。これにより、<wprt:EventControl>要素802を取得するだけの目的でランゲージモニタ36がGetPrinterElementsオペレーションを発行する機会を増やすことがなくなる。更に、ネットワーク4におけるトラフィックを必要最小限に抑えることができ、ネットワーク4上のPCやデバイスに悪影響を与えることがない。
尚、ランゲージモニタ36が、前述したような双方向通信ができるか否かを確認する必要がない場合等では、この例に限られることはない。そのような場合、例えば、ポートモニタ37がCreatePrintJobオペレーションを実行する前、即ち印刷ジョブ要求発行前に、ランゲージモニタ36がGetPrinterElementsオペレーションを実行する。そして、<wprt:EventControl>要素802を事前に取得しても実現することができ、同様な効果を得ることができる。
その際に、ランゲージモニタ36が行っているプリンタキュー32の「印刷後にドキュメントを残す」機能の設定値の確認処理を、上述のGetPrinterElementsオペレーションを実行する前に行っても良い。この確認処理は、図13のS1304や図15で後述するS1504に相当する。この場合、「印刷後にドキュメントを残す」機能の設定値がオフの時だけ、ランゲージモニタ36が<wprt:EventControl>要素802を取得するためにGetPrinterElementsオペレーションを実行すれば良い。
これにより、不要なGetPrinterElementsオペレーションを実行することがなくなる。その結果、不要なリクエスト(GetPrinterElementsRequest)やレスポンス(GetPrinterElementsResponse)の通信も行われないので、ネットワーク4のトラフィックの上昇を防ぐことができる。
図20はプリンタ3におけるCreatePrintJobの処理を表すフローチャートである。図20のフローに係るプログラムは、ROM16に記憶されており、RAM17に読み出され、CPU15により実行される。
図11のS1106において、PC(PC5)からプリンタ3にCreatePrintJobRequest(例えば、図19の(a)のリクエスト)が発行されると、S2001が開始される。プリンタ3は、このリクエストを受信する(S2002)。次に、<wprt:JobName>要素1902にセットされている印刷ジョブ名と<wprt:JobOriginatingUserName>要素1903にセットされているユーザ名を取得する(S2003)。次に、PC5のコンピュータ名(Computer Name)を取得する(S2004)。本実施形態では、WSDのプリントサービス宛てのHTTP POSTでのTCP受信ソケットからIPアドレスを取得し、このIPアドレスに基づいてコンピュータ名を取得する。
尚、ここでは説明を分かり易くするために、このようにIPアドレスからコンピュータ名を取得し、このコンピュータ名を用いてPC(PC5)を特定して各処理を行っているが、IPアドレスを用いてPC5を特定して各処理を行っても良い。
プリンタ3は、取得した印刷ジョブ名とユーザ名とコンピュータ名を一時的に保存する(S2005)。そして、図10の(b)や(c)に示す印刷キューデータベース124を参照し、印刷処理中の印刷ジョブ要求の有無を確認する(S2006)。ここで、印刷処理中の印刷ジョブ要求が有ると判断した場合はS2008へ進み、無いと判断した場合はS2010へ進む(S2007)。S2008では、プリンタ3はPC(PC5)から要求された印刷ジョブ要求にジョブIDを割り当て、この印刷ジョブ要求をStatus「Not Accepted」として印刷キューデータベース124に登録する。そして、印刷ジョブ要求を受け付けることができなかったことを表すFault(ServerErrorNotAcceptingJobs)をPC5に返し(S2009)、この処理を終了する(S2013)。
S2010では、プリンタ3は、PC5から要求された印刷ジョブ要求にジョブIDを割り当て、この印刷ジョブ要求をStatus「Processing」として印刷キューデータベース124に登録する。そして、ジョブIDを<wprt:JobId>要素1904にセットする(S2011)。次に、この印刷ジョブを受け付けて処理することを表す応答であるレスポンス(CreatePrintJobResponse)、例えば図19の(b)を用意する。そして、その中にS2011でセットした<wprt:JobId>要素1904及びその他の各情報をセットし、PC5に返信し(S2012)、この処理を終了する(S2013)。
図9は、プリンタ3におけるGetPrinterElementsの処理を表すフローチャートである。図9は本発明の特徴を最もよく表す図の内の1つである。図9のフローに係るプログラムは、ROM16に記憶されており、RAM17に読み出され、CPU15により実行される。
PCがプリンタ3へGetPrinterElementsRequestを発行したとき、プリンタ3はこれを受けて図9に示す処理を実行する。本発明においてこのリクエストを発行するタイミングとして最も望ましいのは、PCがその印刷ジョブの全ての印刷データをプリンタ3に送信し終わった時である。尚、例えば、その印刷ジョブの印刷開始時や印刷中等、他のタイミングでこの処理を実行しても良い。
図12のS1204において、PC5からプリンタ3にリクエスト(GetPrinterElementsRequest)、例えば図8(a)が発行されると、S901が開始される。プリンタ3がリクエストを受信する(S902)。そして、このリクエストから<wprt:Name>要素(例えば801)にセットされている値を確認し、一時的に保存しておく(S903)。ここで、リクエストの中に複数の<wprt:Name>要素が存在する場合、全ての要素にセットされている値を一時的に保存しておく。
次に、プリンタ3は、<wprt:Name>要素にセットされている値として、wprt:PrinterDescriptionを発見した場合はS905へ進み、発見しなかった場合はS911へ進む(S904)。S905では、プリンタ3は図10の(a)のイベント管理データベース123を参照し、リクエストの発行元のPCに対してWSDのイベントを返すことができるか否かを確認する。その結果、PC5に対してWSDのイベントを返すことができる場合はS907へ進み、返すことができない場合S908へ進む(S906)。
S907では、プリンタ3は、<ans:EventControl>要素802に「true」をセットし、S909へ進む。S908では、プリンタ3は、<ans:EventControl>要素802に「false」をセットし、S909へ進む。S909では、プリンタ3はDevice IDを生成する。このとき、プリンタ3の状態を確認し、その時の状態に応じた値を、Device IDに含まれるプリンタ3の状態を表す情報INFOにセットする。ここでは、オンラインでスタンバイ状態を表す「000」か、印刷処理中(Processing)を表す「001」の何れかがセットされる。
次に、プリンタ3は、<wprt:DeviceId>要素804に、S909で生成されたDevice IDをセットし、S911へ進む(S910)。S911では、プリンタ3は、S907、S908、S910で各情報等がセットされたレスポンス(GetPrinterElementsResponse)をS902で受信したリクエストに対する応答としてPC5に返信する。そして、この処理を終了する(S912)。
図21はプリンタ3におけるGetActiveJobsの処理を表すフローチャートである。図21のフローに係るプログラムは、ROM16に記憶されており、RAM17に読み出され、CPU15により実行される。
図12のS1208又は図16のS1602において、PC5からプリンタ3にリクエスト(GetActiveJobsRequest)、例えば図14の(a)が発行され、S2101が開始される。プリンタ3は、このリクエストを受信した後(S2102)、図10の(b)や(c)に示す印刷キューデータベース124を参照し、印刷処理中の印刷ジョブ要求の有無を確認する(S2103)。ここで、印刷処理中の印刷ジョブ要求が有ると判断した場合はS2105へ進み、無いと判断した場合はS2107へ進む(2104)。S2105では、プリンタ3は<wprt:JobSummary>要素1401に、印刷処理中の印刷ジョブ要求に関する以下に示すような各情報をセットする。
<wprt:JobId>要素1402
<wprt:JobState>要素1404
<wprt:JobName>要素1405
<wprt:JobOriginatingUserName>要素1406
例えば、プリンタ3が複数の印刷ジョブ要求を同時に受け付けて処理できるような印刷キューを備え、同時に印刷処理中の場合、全ての印刷ジョブ要求に対してそれぞれ<wprt:JobSummary>要素を用意する。そして、その中にそれぞれの印刷ジョブ要求に関する各情報をセットする。
プリンタ3は、<wprt:ActiveJobs>要素1403に、S2105で用意した<wprt:JobSummary>要素1401をセットする(S2106)。S2107では、プリンタ3は、S2106でセットした<wprt:ActiveJobs>要素1403及びその他の各情報がセットされたレスポンス(GetActiveJobsResponse)をリクエストに対する応答としてPC5に返信する。そして、この処理を終了する(S2108)。
実施形態1で説明した周辺装置制御システムは、印刷中の記録紙のジャムをリカバリーして、ジャムが発生して印刷に失敗したページから再印刷する紙ジャムエラーリカバリー処理に対応している。
この紙ジャムエラーリカバリー処理の詳細は、次に示す通りである。ランゲージモニタ36は、ある印刷ジョブを印刷中にプリンタ3から印刷中のページ番号とエラーの有無の情報を、例えば5秒に1回の時間間隔で定期的に取得する。そして、取得した情報を印刷制御に関する情報を保存するための印刷制御用構造体(不図示、物理的にはRAM201に該当)に保存する。記録紙のジャムが発生した場合、ランゲージモニタ36はプリンタ3から紙ジャムエラー情報を取得し、その紙ジャムエラー情報を印刷制御用構造体に保存する。
この状態において、印刷制御用構造体には、紙ジャムエラー情報と、紙ジャムエラーが発生したページ番号が保存されている。LM_WritePort()関数内において、ランゲージモニタ36は、SetJob()関数を利用してその第5引数のCommandにJOB_CONTROL_RESTARTという値をセットする。そして、印刷ジョブを再印刷するために、この関数をコールした後、LM_WritePort()関数の処理を終了して呼び出し元であるスプーラ40に処理を戻す。
スプーラ40は、印刷ジョブを再印刷するための新しい印刷ジョブを生成し、プリンタキュー32にその新しい印刷ジョブをスタックし、ランゲージモニタ36のLM_EndDocPort()関数をコールする。ランゲージモニタ36は図13に示すLM_EndDocPort()関数の処理を実行し、S1301とS1302の間でプリンタ3にリセットコマンドを送信し、その後、S1302及びそれ以降の処理を実行し、呼び出し元であるスプーラ40に処理を戻す。
プリンタ3は、リセットコマンドを受信すると、RAM17に一時的に格納されている紙ジャムエラーを発生した印刷ジョブの残りの印字データを破棄し、エラー状態を解除する。このとき、プリンタ3は、Device IDの中に含まれるプリンタ3の状態を表す情報INFO:に、オンラインでスタンバイ状態を表す「000」をセットする。スプーラ40は、紙ジャムエラーを発生した印刷ジョブを修了し、再印刷用の新しい印刷ジョブを開始する。
ランゲージモニタ36は、LM_WritePort()関数内でこの再印刷された新しい印刷ジョブの印字データを受け取った後、印刷制御用構造体を参照する。ここで紙ジャムエラー情報がセットされている場合は、紙ジャムエラーが発生したページ番号を参照し、その前のページまでの印字データをプリンタ3へ送信せずに読み捨てる。そして、紙ジャムエラーが発生したページ及びそれ以降のページの印字データをプリンタ3へ送信する。
プリンタ3は、印字データに従って印刷処理を実行し、紙ジャムエラーが発生したページから再印刷を行う。紙ジャムエラーリカバリー処理中に、ランゲージモニタ36がLM_EndDocPort()関数の処理を実行し、印刷終了を表すイベントを通知できない場合、S1306でプリンタキュー32から紙ジャムエラーを発生した印刷ジョブを削除する。
このように、紙ジャムエラーリカバリー処理中において、紙ジャムエラーで印刷に失敗した印刷ジョブをランゲージモニタ36がステップS1306でプリンタキュー32から削除する。これにより、紙ジャムエラーで印刷に失敗した印刷ジョブが、「Sent to printer」のステータス(Status)の状態でプリンタキュー32に残ることがなく、操作性に優れた周辺装置制御システムを実現することができる。
実施形態では周辺装置の例としてプリンタ3を挙げたが、プリンタ、FAX、スキャナ、ストレージ等を搭載したマルチファンクションプリンタ(MFP)にも、本発明は有効である。WSDを搭載したMFPの場合、プリンタ、FAX、スキャナのそれぞれの機能に対して次に示すようなWSDの各Serviceを割り当てることが可能である。
機能 WSDのサービス 備考
プリンタ プリントサービス プリンタ機能用
FAX プリントサービス FAX機能用
スキャナ スキャンサービス
ここで、各機能のサービスに割り当てられているServiceIdは、次の通りである。
プリンタ: <wsdp:ServiceId>http://schemas.abc.xxx/Printer</wsdp:ServiceId>
FAX: <wsdp:ServiceId>http://schemas.abc.xxx/Fax</wsdp:ServiceId>
スキャナ: <wsdp:ServiceId>http://schemas.abc.xxx/Scanner</wsdp:ServiceId>
プリンタ機能及びFAX機能には、どちらもプリントサービスが割り当てられており、ServiceIDがプリンタ機能用とFAX機能用とで異なっている。そのため、プリンタ機能及びFAX機能のServiceTypeは、どちらもPrinterServiceTypeとなる。
上述した通り、ランゲージモニタ36は、WSDAPIsのGetPrinterElements()関数を使ってPC5からプリンタ3にGetPrinterElementsRequestを発行する。そしてプリンタ3からPC5に返されるGetPrinterElementsResponseを受け取ることができる。このとき、GetPrinterElements()関数に次に示すようにServiceTypeを指定してこの関数をコールすることで、GetPrinterElementsを利用することができる。
<portType name="PrinterServiceType" wse:EventSource="true">
<operation name="GetPrinterElements">
<input message="wprt:GetPrinterElementsRequestMsg"
wsa:Action="http://schemas.yyyy.xxx/YYYY/MM/wdp/print/
GetPrinterElements" />
<output message="wprt:GetPrinterElementsResponseMsg"
wsa:Action="http://schemas.yyyy.xxx/YYYY/MM/wdp/print/
GetPrinterElementsResponse" />
</operation>
</portType>
しかしながら、MFPの場合、プリンタ機能及びFAX機能のServiceTypeはどちらもPrinterServiceTypeという同一のタイプである。そのため、ServiceTypeを指定して上述の関数をコールしても、プリンタ機能とFAX機能を区別してその機能に関する情報を取得することができない、という問題に直面する。そこで、MFPの場合、ランゲージモニタ36がServiceIDを指定して関数をコールすることでプリンタ機能又はFAX機能を指定し、指定した機能に関する情報をGetPrinterElementsを利用して取得することができる。これにより、プリンタ機能とFAX機能とを備えるMFPに対しても、誤動作を防止して正確な制御が可能な周辺装置制御システムを実現することができる。
<実施形態2>
実施形態1では、プリンタ3が複数の印刷ジョブを同時に受け付けて処理することができず、1つの印刷ジョブだけを受け付けて処理することができる例を挙げた。実施形態2では、ランゲージモニタ36が、自身が発行(送信)した印刷ジョブのプリンタ3における印刷が終了したか否かを見とどけ、必要に応じてプリンタキュー32からその印刷ジョブを削除する方法を説明する。
しかしながら、例えばプリンタ3が複数の印刷ジョブ要求を同時に受け付けて処理することができるような印刷キューを備える場合、ランゲージモニタ36が発行(送信)した印刷ジョブが、必ずしもプリンタ3において直ちに印刷されるわけではない。プリンタ3内の印刷キューに入るだけで、印刷が開始されないケースも存在する。
ここで、プリンタ3が10個の印刷ジョブを同時に受け付けて処理できる場合、PC1において印刷ジョブ144の印刷が行われ、プリンタ3がPC1から発行された印刷ジョブ要求を印刷中にPC5において同時に複数の印刷が行われる。そして複数の印刷ジョブがPC5内のプリンタキュー32にスタックされるような例を考える。
まず、PC5において、スプーラ40がプリンタキュー32にスタックされている1つ目の印刷ジョブ145の印刷を開始すると、PC5はプリンタ3にこの印刷ジョブ145の印刷ジョブ要求を発行する。プリンタ3は、PC1から発行された印刷ジョブ要求を受け付けて印刷中であるため、プリンタ3内の印刷キューにPC5から送られてくる印字データを格納するものの、PC5から発行された印刷ジョブ要求の印刷処理を開始することはできない。
PC5(ランゲージモニタ36)が印刷ジョブ145の全ての印字データをプリンタ3に送信し終わると、ランゲージモニタ36は、図13のS1302、S1311、S1303を繰り返す。そして、その印刷ジョブ145のプリンタ3における印刷が終了することを確認する(見とどける)。しかしながら、ランゲージモニタ36は、プリンタ3において未だ印刷が開始されていない印刷ジョブ145の印刷状況を監視して、その印刷が終了するまで見とどけることになる。そのため、スプーラ40に制御を戻すことができず、PC5(スプーラ40)は次の印刷ジョブ(不図示)を発行することができない。このような問題に対する解決策を図15及び図16を用いて説明する。
図15はランゲージモニタ36におけるLM_EndDocPort()関数の処理を表すフローチャートである。図15は本発明の特徴を最もよく表す図の内の1つである。図15のフローに係るプログラムは、HDD202に記憶されており、RAM201に読み出され、CPU204により実行される。
PCがプリンタ3に対して印刷ジョブを発行して印刷を行うケースにおいて、PCがその印刷ジョブの全ての印刷データをプリンタ3に送信後、スプーラ40がLM_EndDocPort()関数をコールする。そして、ランゲージモニタ36がこのLM_EndDocPort()関数の処理を開始する。
図6のS608において、スプーラ40がランゲージモニタ36のLM_EndDocPort()関数をコールすると、図15において、ランゲージモニタ36がこの関数の処理を開始する(S1501)。ランゲージモニタ36は、ポートモニタ37のPM_EndDocPort()関数をコールし、その関数の戻り値をlmRetに代入する(S1502)。ランゲージモニタ36は、lmDeleteJobの値を確認し、TRUEの場合はS1504へ進み、TRUEではない(FALSEである)場合はS1507へ進む(S1503)。
S1504では、ランゲージモニタ36はプリンタキュー32の「印刷後にドキュメントを残す」機能の設定値を確認し、オンの場合はS1507へ進み、オフの場合はS1506へ進む。S1506では、ランゲージモニタ36は、別プロセスを起動し、そのプロセスの中で図16に示す印刷ジョブの監視と削除の処理を実行する。
また、S1507では、ランゲージモニタ36は、lmDeleteJobにFALSEを代入して初期化し、lmJobIdに0を代入して初期化する(S1508)。ランゲージモニタ36は、LM_EndDocPort()関数の戻り値として、lmRetをスプーラ40に返し、LM_EndDocPort()関数の処理を終了し、呼び出し元であるスプーラ40に戻る(S1505)。
図16はランゲージモニタ36における印刷ジョブの監視と削除の処理を表すフローチャートである。図16は本発明の特徴を最もよく表す図の内の1つである。図16のフローに係るプログラムは、HDD202に記憶されており、RAM201に読み出され、CPU204により実行される。
図15のS1506において、ランゲージモニタ36が別プロセスを起動して印刷ジョブの監視と削除の処理を実行すると、図16において、ランゲージモニタ36が印刷ジョブの監視と削除の処理を開始する(S1601)。ランゲージモニタ36は、WSDを制御するWSDAPIsのGetActiveJobs関数をコールする(S1602)。この関数内において、PC5はWSDのプリントサービスのリクエスト(GetActiveJobsRequest)をプリンタ3に発行する。このリクエストに対して、プリンタ3はレスポンス(GetActiveJobsResponse)をPC5に返信する(S1602)。PC5がレスポンスを受け取ると、GetActiveJobs関数の戻り値にTRUEを代入し、呼び出し元に戻る(S1602)。
PC5がプリンタ3に対してリクエストを発行後、一定時間内にレスポンスを受け取らなかった場合、GetActiveJobs関数の戻り値にFALSEを代入し、呼び出し元に戻る(S1602)。S1602において、ランゲージモニタ36はGetActiveJobs関数の戻り値をlmRetに代入する。尚、ここでは、GetActiveJobs関数の戻り値としてFALSEが返されるようなエラーケースの説明は省略する。
S1602でPCが発行するリクエストと、リクエストに対してプリンタ3が返信するレスポンスの詳細に関しては図14で説明する。ランゲージモニタ36は、S1602のGetActiveJobs関数の引数として渡されたレスポンス内の<wprt:ActiveJobs>要素1403内の各<wprt:JobSummary>要素にセットされている情報を取得する(S1603)。そして、ランゲージモニタ36は、それぞれの<wprt:JobSummary>要素内の<wprt:JobId>要素にセットされている値を取得して、lmJobIdと同じ番号の印刷処置中の印刷ジョブの有無を確認する(S1603)。ランゲージモニタ36が、<wprt:ActiveJobs>要素1403内の各<wprt:JobSummary>要素に含まれる<wprt:JobId>要素の中に、lmJobIdと同じ値が有ると判断した場合はS1602に戻る。
また、無いと判断した場合はS1605へ進み、ランゲージモニタ36は、lmJobIdにセットされているジョブIDの印刷ジョブをプリンタキュー32から削除する。そして、ランゲージモニタ36は印刷ジョブの監視と削除の処理を終了し、これに伴い、このプロセスも終了する(S1606)。
図15のS1506において、ランゲージモニタ36が別プロセスを起動して印刷ジョブの監視と削除の処理を実行する。これにより、図16に示す印刷ジョブの監視と削除処理の終了を待つことなく、図15のS1507、S1508、S1505の処理が行われ、呼び出し元であるスプーラ40に制御を戻すことができる。
よって、プリンタ3が複数の印刷ジョブ要求を同時に受け付けて処理できるような印刷キューを備える場合にも、プリンタ3における他の印刷ジョブ要求の印刷処理状況の影響を受けることなく、処理できる。即ち、PC5(スプーラ40)がプリンタキュー32にスタックされた複数の印刷ジョブを、プリンタ3に順次発行することができる。
更に、図10の(a)で示されるケースにおいて、プリンタ3が、印刷が終了したことを表すJobEndStateEventのイベントをPC5に返信することができない場合にも、印刷が終了した印刷ジョブ(印刷ジョブ145)を削除できる。即ち、図18の(e)に示すようにPC5内のプリンタキュー32から自動的に削除することができるので、ユーザの操作性に優れる。
尚、図15のステップS1506において、ランゲージモニタ36が別プロセスを起動して印刷ジョブの監視と削除の処理を実行する例を挙げたが、この例に限られるものではない。例えば、既に別プロセスで起動中のステータスモニタ39で、図16に示すような印刷ジョブの監視と削除の処理を実行することでも、実現可能であり、同様な効果を得ることができる。
また、例えばネットワーク4上の複数のプリンタの状態や印刷ジョブの状況を表示し、プリンタや印刷ジョブを操作することができるようなプリンタ管理アプリケーション(不図示)等で図16に示すような印刷ジョブの監視と削除の処理を実行する。これによっても、実現可能であり、同様な効果を得ることができる。
実施形態2では、プリンタ3において実際に印刷ジョブが処理されて、印刷が完了した時点で、プリンタキュー32からその印刷ジョブを削除する例(第1の例)を挙げたが、この例以外にも本発明を適用することができる。
PC5からプリンタ3へある印刷ジョブの印字データを全て送信し、プリンタ3がその印字データを全て受信した時点でプリンタキュー32からその印刷ジョブを削除するようにしても良い(第2の例)。即ち、その印刷ジョブのステータス(Status)が「Sent to printer」に変わった時点で、プリンタキュー32からその印刷ジョブを削除する。この例の場合、PC1からプリンタ3へ印刷ジョブが発行されたケースでは、プリンタ3は、その印刷ジョブの印字データを全て受信した時点で、PC1に印刷終了を表すイベントを通知する。
PC1において、ポートモニタは、このイベントを受信すると、プリンタキューからその印刷ジョブを削除する。PC5からプリンタ3へ印刷ジョブが発行されたケースでは、プリンタ3は、その印刷ジョブの印字データを全て受信した時点で、PC5に印刷終了を表すイベントを通知できない。そのため、ここでは、ランゲージモニタが、図16に示すようなGetActiveJobsオペレーションを利用した印刷ジョブの監視と削除の処理を行うことで、プリンタキュー32からその印刷ジョブを削除する。
但し、図16では、ランゲージモニタ36が、S1604でその印刷ジョブの有無を確認し、印刷ジョブが無い場合にS1605においてプリンタキュー32からその印刷ジョブを削除していたが、代わりに次に示すような処理を行う。
ランゲージモニタ36は、印刷ジョブがある場合、その印刷ジョブのJobStateがPendingで、かつJobStateReasonがJobIncomingであるか否かを確認する。確認の結果、YESの場合、ランゲージモニタ36はS1605へ進み、プリンタキュー32からその印刷ジョブを削除する。それ以外の場合はS1602へ戻る。このように、ランゲージモニタ36が、プリンタキュー32から印刷ジョブを削除する方法は、プリンタ3又は周辺装置制御システムの種類により複数の例が考えられる。
実施形態2で説明した第1の例が最も一般的であると考えられる。実施形態2で説明した第2の例は、プリンタ3の処理能力が高く、信頼性も高いような、印刷に失敗することや印刷に時間を要すことがほとんど無いケースにおいて、PC内のプリンタキューの表示が見やすくなる、という効果がある。
今、実施形態1で説明した1つの印刷ジョブだけを受け付けて処理できるプリンタと、実施形態2で説明した複数の印刷ジョブ要求を同時に受け付けて処理できるプリンタを、1つのプリンタドライバ50で制御するケースを考える。
図6のS606の後に、ランゲージモニタ36は、LM_StartDocPort()関数内においてlmMultipleJobsにFALSEを代入して初期化する。また、図6のS616の後に、ランゲージモニタ36はLM_EndDocPort()関数内においてlmMultipleJobsにFALSEを代入して初期化する。このlmMultipleJobsはランゲージモニタ36内で使用されるフラグであり、プリンタ3が1つの印刷ジョブだけを受け付けて処理できるプリンタである場合にFALSEがセットされる。また、複数の印刷ジョブ要求を同時に受け付けて処理できるプリンタである場合にはTRUEがセットされる。
S1204、S1205において、ランゲージモニタ36は、引数にwprt:PrinterDescriptionをセットし、WSDを制御するWSDAPIsのGetPrinterElements()関数をコールする。そして、<ans:EventControl>要素802にセットされている値を取得する。このとき、ランゲージモニタ36は、<ans:MultipleJobsControl>要素807にセットされている値も取得する。この値が「true」の場合、ランゲージモニタ36はlmMultipleJobsにTRUEをセットする。
ここで、図13のS1301と図15のS1501は同一の関数ポインタであると仮定する。図6のS609において、ランゲージモニタ36は、LM_EndDocPort()関数の処理を開始した直後(S610の前)に、lmMultipleJobsにセットされている値を確認する。ここで、FALSEの場合は図13のS1302へ進み、TRUEの場合は図15のS1502へ進む。
これにより、プリンタドライバ50が、実施形態1で説明したプリンタと、実施形態2で説明したプリンタとを、自動的に判別して制御し、本発明の実施形態1と実施形態2を実現することができる。
<実施形態3>
実施形態1で説明したように、一般的にプリンタがPCへ通知するイベントの制御に関しては、そのプリンタのハードウェアリソースの制限の影響を大きく受ける。具体的な例を挙げると、例えば実施形態1の図10の(a)に示す例では、プリンタ3はPC1とPC2に対してイベントを通知することができるが、PC5に対してイベントを通知することができない。
実施形態3では、この問題を解決し、しかも、本発明の課題も解決する例を、図10の(d)と図17を用いて説明する。図10の(d)は、プリンタ3がPCに通知するWSDのイベントを管理するイベント管理データベースを表す図である。この図は本発明の特徴を最もよく表す図の内の1つである。
実施形態3では、PCに通知するイベントの数を制限することで、プリンタがイベントを通知できるPCの数を増やす方法を提案する。図10の(d)に示すイベント管理データベース125は以下のように構成されている。
Subscribed Event欄には、PCから発行されたWSDの各イベントの登録要求が保存されている。次のans:EventControl2欄には、各イベントの登録要求に対して、プリンタ3が登録を許可したか否かを表す情報が保存されている。ここで、「true」はそのイベントの登録要求に対して許可したことを表し、「false」はそのイベントの登録要求に対して拒絶したことを表す。また、プリンタ3が、WSDのプリントサービスで定義されている6つのイベントの内、以下に示すの2つのイベントだけをPCに通知し、それ以外の4つのイベントの通知は行わない例を示している。
JobStatusEvent(処理状況を表すイベント)
JobEndStateEvent(印刷が終了したことを表すイベント)
これら2つのイベントは、PC内のプリンタキューにおいて、スプーラが印刷ジョブを制御する際に利用される。この例では、プリンタ3は、PC1、PC2、PC5に対して2つのイベントの通知を行うことができる状態であることを示している。従って、プリンタ3は、図10の(b)に示すような、管理番号(No.)1のPC5からの印刷ジョブ要求に対して、その処理状況を表すイベントや印刷が終了したことを表すイベントをPC5に通知することができる。
図17の(a)はGetPrinterElementsRequest、(b)はGetPrinterElementsResponseをそれぞれ表す。図は本発明の特徴を最もよく表す図の内の1つである。図17の(a)、(b)において、図8で既に説明した要素801、806、803、805、804に関しては、その説明を省略する。
図17の(a)は、PC5がプリンタ3に発行するリクエストの一例である。<ans:EventControl2>要素1701はプライベート情報である。プリンタ3がPCに対してWSDのプリントサービスDefinition Version 1.0で定義されている各イベントを通知することができるか否かを表す情報が含まれている。
<ans:PrinterElementsChangeEvent>要素1702には、次のようにセットされる。プリンタ3がPCに対してPrinterElementsChangeEventを通知することができる場合は「true」がセットされる。また通知することができない場合は「false」がセットされる。この例では、「false」がセットされており、プリンタ3がそのPCに対してこのイベントを通知することができない状態を表す。
<ans:PrinterStatusSummaryEvent>要素1703には、次のようにセットされる。プリンタ3がPCに対してPrinterStatusSummaryEventイベントを通知することができる場合は「true」がセットされる。また通知することができない場合は「false」がセットされる。この例では、「false」がセットされており、プリンタ3がそのPCに対してこのイベントを通知することができない状態を表す。
<ans:PrinterStatusConditionEvent>要素1704には、次のようにセットされる。プリンタ3がPCに対してPrinterStatusConditionEventを通知することができる場合は「true」がセットされる。また通知することができない場合は「false」がセットされる。この例では、「false」がセットされており、プリンタ3がそのPCに対してこのイベントを通知することができない状態を表す。
<ans:PrinterStatusConditionClearedEvent>要素1705には、次のようにセットされる。プリンタ3がPCに対してPrinterStatusConditionClearedEventを通知することができる場合は「true」がセットされる。また通知することができない場合は「false」がセットされる。この例では、「false」がセットされており、プリンタ3がそのPCに対してこのイベントを通知することができない状態を表す。
<ans:JobStatusEvent>要素1706には、次のようにセットされる。プリンタ3がPCに対してJobStatusEventイベントを通知することができる場合は「true」がセットされる。また通知することができない場合は「false」がセットされる。この例では、「true」がセットされており、プリンタ3がそのPCに対してこのイベントを通知することができる状態を表す。
<ans:JobEndStateEvent>要素1707には、次のようにセットされる。プリンタ3がPCに対してJobEndStateEventを通知することができる場合は「true」がセットされる。また通知することができない場合は「false」がセットされる。この例では、「true」がセットされており、プリンタ3がそのPCに対してこのイベントを通知することができる状態を表す。
実施形態3では、実施形態1の<ans:EventControl>要素802の代わりに<ans:JobEndStateEvent>要素1707を代用することで、本発明の課題を解決する。
図9のS907、S908において、<ans:EventControl>要素802の代わりに<ans:JobEndStateEvent>要素1707を代用する。図11のS1110、S1112において、<ans:EventControl>要素802の代わりに<ans:JobEndStateEvent>要素1707を代用する。図12のS1205、S1206において、<ans:EventControl>要素802の代わりに<ans:JobEndStateEvent>要素1707を代用する。
このように、図10の(d)で示されるケースにおいて、PC888からの印刷ジョブ要求に対してプリンタ3が、印刷が終了したことを表すイベントを返せなくても、印刷が終了した印刷ジョブを、PC888内のプリンタキューから削除できる。よって、ユーザの操作性に優れる。
<実施形態4>
本発明の実施の形態では、プリンタの例としてカラーインクジェットプリンタを使用したが、この例に限られることなく、例えば、モノクロLBP等の任意のプリンタを使用することができる。
実施形態では情報処理装置としてパーソナルコンピュータを想定した。しかし、これに限ることなく、DVDプレーヤー、ゲーム、セットトップボックス、インターネット家電等、同様な使用方法が可能な任意の情報処理装置(端末)に対して実現することができ、有効である。
本発明の実施の形態では、周辺装置としてプリンタを例示しているが、周辺装置として他に、複写機、ファクシミリ、スキャナ、デジタルカメラ、デジタルビデオカメラ、及びこれらの複合機能を備える装置等の何れかが、本発明の適用対象となり得る。
本発明の実施の形態では、PC1、PC2、PC5、PC888とプリンタ3との間のインタフェースとして、例えば無線LAN、IEEE1394、Bluetooth(登録商標)等の任意のインタフェースを用いるようにしても良い。
本発明の実施の形態では、Webサービスのプロトコルの例としてWSDを挙げたが、この例に限られることなく、例えばIHVの独自プロトコル等の任意のプロトコルを用いるようにしても良い。
本発明の実施の形態では、WSDのプリントサービス宛てのHTTP POSTでのTCP受信ソケットからIPアドレスを取得し、このIPアドレスをもとにコンピュータ名取得して、このコンピュータ名を用いてPCを特定している。この例に限られることなく、例えば、WSDのプリントサービス宛てのHTTP POSTでのTCP受信ソケットからIPアドレスを取得して、このIPアドレスを用いてPCを特定する等の、他の手段を利用してPCを特定しても良い。
このようにIPアドレスを利用することで、WSDのプロトコル内で2バイトコードを取り扱うような考慮が不要となり、プログラムを簡素化でき、コーディングミスを最小限に抑えることができるので、品質を向上することができる。
本発明の実施の形態では、GetPrinterElementsオペレーションを利用して<ans:EventControl>要素や<ans:JobEndStateEvent>要素を取得する例を挙げた。この例に限らず、プリンタに関する情報を取得するオペレーションの代わりに、印刷ジョブに関する情報を取得するオペレーションを利用しても良い。そのオペレーションとしてはGetJobElementsオペレーション等のWSDのプリントサービスDefinitionで定義されているオペレーションである。
本発明の実施の形態では、PCが、プリンタから取得する<wprt:DeviceId>要素804にセットされているDevice IDの中に含まれるプリンタの状態を表す情報(INFO:xxx)を参照する。そして、この情報にセットされている値からプリンタにおける印刷が終了してオンラインでスタンバイ状態(「000」)か、印刷中(「001」)かを判断する例を挙げた。この例に限られることなく、例えば、プリンタの状態をSNMP等の別のプロトコルやコマンドを利用して取得し、その結果をもとにプリンタにおける印刷ジョブ要求の処理状況を判断しても良い。
[他の実施形態]
また、本発明は、以下の処理を実行することによっても実現される。即ち、上述した実施形態の機能を実現するソフトウェア(プログラム)を、ネットワーク又は各種記憶媒体を介してシステム或いは装置に供給し、そのシステム或いは装置のコンピュータ(またはCPUやMPU等)がプログラムを読み出して実行する処理である。