diff --git a/libprs500/communicate.py b/libprs500/communicate.py index 0088d3a2f1..60c26778fe 100755 --- a/libprs500/communicate.py +++ b/libprs500/communicate.py @@ -221,8 +221,12 @@ class PRS500Device(object): self.device = self.device_descriptor.getDevice() if not self.device: raise DeviceError() - self.handle = self.device.open() - self.handle.claimInterface(self.device_descriptor.interface_id) + try: + self.handle = self.device.open() + self.handle.claimInterface(self.device_descriptor.interface_id) + except usb.USBError, e: + print >>sys.stderr, e + raise DeviceBusy() res = self._send_validated_command(GetUSBProtocolVersion(), timeout=20000) # Large timeout as device may still be initializing if res.code != 0: raise ProtocolError("Unable to get USB Protocol version.") version = self._bulk_read(24, data_type=USBProtocolVersion)[0].version @@ -236,8 +240,10 @@ class PRS500Device(object): def close(self): """ Release device interface """ - self.handle.reset() - self.handle.releaseInterface() + try: + self.handle.reset() + self.handle.releaseInterface() + except: pass self.handle, self.device = None, None def _send_command(self, command, response_type=Response, timeout=1000): diff --git a/libprs500/errors.py b/libprs500/errors.py index 004bae1559..35fea0d905 100644 --- a/libprs500/errors.py +++ b/libprs500/errors.py @@ -34,6 +34,11 @@ class DeviceError(ProtocolError): def __init__(self): ProtocolError.__init__(self, "Unable to find SONY Reader. Is it connected?") +class DeviceBusy(ProtocolError): + """ Raised when device is busy """ + def __init__(self): + ProtocolError.__init__(self, "Device is in use by another application") + class PacketError(ProtocolError): """ Errors with creating/interpreting packets """ diff --git a/libprs500/gui/__init__.py b/libprs500/gui/__init__.py index 48419ab513..0393658c12 100644 --- a/libprs500/gui/__init__.py +++ b/libprs500/gui/__init__.py @@ -13,7 +13,8 @@ ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. __docformat__ = "epytext" -__author__ = "Kovid Goyal " +__author__ = "Kovid Goyal " +APP_TITLE = "libprs500" import pkg_resources, sys, os, re, StringIO, traceback from PyQt4 import QtCore, QtGui # Needed for classes imported with import_ui @@ -28,7 +29,7 @@ def installErrorHandler(dialog): global error_dialog error_dialog = dialog error_dialog.resize(600, 400) - error_dialog.setWindowTitle("SONY Reader - Error") + error_dialog.setWindowTitle(APP_TITLE + " - Error") error_dialog.setModal(True) diff --git a/libprs500/gui/main.py b/libprs500/gui/main.py index c786c86dce..6d53124307 100644 --- a/libprs500/gui/main.py +++ b/libprs500/gui/main.py @@ -20,12 +20,12 @@ from PyQt4 import uic from libprs500.communicate import PRS500Device as device from libprs500.errors import * from libprs500.lrf.meta import LRFMetaFile, LRFException -from libprs500.gui import import_ui, installErrorHandler, Error, Warning, extension +from libprs500.gui import import_ui, installErrorHandler, Error, Warning, extension, APP_TITLE from libprs500.gui.widgets import LibraryBooksModel, DeviceBooksModel, DeviceModel, TableView from database import LibraryDatabase from editbook import EditBookDialog -import sys, re, os, traceback +import sys, re, os, traceback, tempfile DEFAULT_BOOK_COVER = None LIBRARY_BOOK_TEMPLATE = QString("
Formats: %1 Tags: %2
Comments:%3
") @@ -102,7 +102,7 @@ class MainWindow(QObject, Ui_MainWindow): def delete(self, action): count = str(len(self.current_view.selectionModel().selectedRows())) - ret = QMessageBox.question(self.window, self.trUtf8("SONY Reader - confirm"), self.trUtf8("Are you sure you want to permanently delete these ") +count+self.trUtf8(" item(s)?"), QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) + ret = QMessageBox.question(self.window, self.trUtf8(APP_TITLE + " - confirm"), self.trUtf8("Are you sure you want to permanently delete these ") +count+self.trUtf8(" item(s)?"), QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if ret != QMessageBox.Yes: return self.window.setCursor(Qt.WaitCursor) if self.library_view.isVisible(): @@ -342,7 +342,7 @@ class MainWindow(QObject, Ui_MainWindow): def device_removed(self, timeout=False): """ @todo: only reset stuff if library is not shown """ self.is_connected = False - self.df.setText("SONY Reader:

Storage card:") + self.df.setText(self.df_template.arg("").arg("").arg("")) self.device_tree.hide_reader(True) self.device_tree.hide_card(True) self.book_cover.hide() @@ -368,13 +368,15 @@ class MainWindow(QObject, Ui_MainWindow): self.status("Connecting to device") try: info = self.dev.get_device_information(end_session=False) + except DeviceBusy, e: + qFatal(str(e)) except DeviceError: self.dev.reconnect() return except ProtocolError, e: traceback.print_exc(e) qFatal("Unable to connect to device. Please try unplugging and reconnecting it") - self.df.setText(self.df_template.arg(info[0]).arg(info[1]).arg(info[2])) + self.df.setText(self.df_template.arg("Connected: "+info[0]).arg(info[1]).arg(info[2])) space = self.dev.available_space(end_session=False) sc = space[1][1] if space[1][1] else space[2][1] self.device_tree.model().update_free_space(space[0][1], sc) @@ -395,6 +397,11 @@ class MainWindow(QObject, Ui_MainWindow): def main(): from optparse import OptionParser from libprs500 import __version__ as VERSION + lock = os.path.join(tempfile.gettempdir(),"libprs500_gui_lock") + if os.access(lock, os.F_OK): + print >>sys.stderr, "Another instance of", APP_TITLE, "is running" + print >>sys.stderr, "If you are sure this is not the case then manually delete the file", lock + sys.exit(1) parser = OptionParser(usage="usage: %prog [options]", version=VERSION) parser.add_option("--log-packets", help="print out packet stream to stdout. "+\ "The numbers in the left column are byte offsets that allow the packet size to be read off easily.", \ @@ -405,12 +412,17 @@ def main(): global DEFAULT_BOOK_COVER DEFAULT_BOOK_COVER = QPixmap(":/default_cover") window = QMainWindow() + window.setWindowTitle(APP_TITLE) window.setWindowIcon(QIcon(":/icon")) installErrorHandler(QErrorMessage(window)) QCoreApplication.setOrganizationName("KovidsBrain") - QCoreApplication.setApplicationName("SONY Reader") + QCoreApplication.setApplicationName(APP_TITLE) gui = MainWindow(window, options.log_packets) - ret = app.exec_() + f = open(lock, "w") + f.close() + try: + ret = app.exec_() + finally: os.remove(lock) return ret if __name__ == "__main__": main() diff --git a/libprs500/gui/main.ui b/libprs500/gui/main.ui index 63d7fa2773..939e783d87 100644 --- a/libprs500/gui/main.ui +++ b/libprs500/gui/main.ui @@ -19,7 +19,10 @@ - SONY Reader + + + + :/images/library.png @@ -60,7 +63,7 @@ Qt::ScrollBarAlwaysOff - QAbstractItemView::DropOnly + QAbstractItemView::DragDrop QListView::TopToBottom @@ -84,11 +87,14 @@ - <b>libprs500</b> was created by <b>Kovid Goyal</b> &copy; 2006<br><br>%1 %2 %3 + For help visit <a href="http://libprs500.kovidgoyal.net">http://libprs500.kovidgoyal.net</a><br><br><b>libprs500</b> was created by <b>Kovid Goyal</b> &copy; 2006<br>%1 %2 %3 Qt::RichText + + true + @@ -275,8 +281,8 @@ - 49 - 37 + 163 + 58 @@ -291,6 +297,9 @@ 22 + + Qt::ToolButtonTextUnderIcon + 4 @@ -303,7 +312,7 @@ :/images/plus.png - Add files to Library + Add books to Library A @@ -317,7 +326,7 @@ :/images/minus.png - Delete selected items + Delete books Del @@ -328,7 +337,7 @@ :/images/edit.png - Edit meta-information for the currently selected items + Edit meta-information E diff --git a/libprs500/gui/widgets.py b/libprs500/gui/widgets.py index f0c2562ce3..d32f50a1ff 100644 --- a/libprs500/gui/widgets.py +++ b/libprs500/gui/widgets.py @@ -116,9 +116,7 @@ class FileDragAndDrop(object): urls.append(urlunparse(('file', quote(gethostname()), quote(str(file.name)), '','',''))) self._dragged_files.append(file) mime_data.setData("text/uri-list", QByteArray("\n".join(urls))) - user = None - try: user = os.environ['USER'] - except: pass + user = os.getenv['USER'] if user: mime_data.setData("text/x-xdnd-username", QByteArray(user)) drag.setMimeData(mime_data) return drag