From f42faa0cb72508498e0a89b9a680214bd44eda4e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 26 Dec 2009 11:21:48 -0700 Subject: [PATCH] New recipe for The COlumbus Dispatch by kwetal --- resources/images/news/columbusdispatch.png | Bin 0 -> 952 bytes resources/recipes/columbusdispatch.recipe | 80 ++++++++++++++++++ src/calibre/devices/usbobserver/Makefile | 6 +- src/calibre/devices/usbobserver/usbobserver.c | 44 ++++++---- 4 files changed, 108 insertions(+), 22 deletions(-) create mode 100644 resources/images/news/columbusdispatch.png create mode 100644 resources/recipes/columbusdispatch.recipe diff --git a/resources/images/news/columbusdispatch.png b/resources/images/news/columbusdispatch.png new file mode 100644 index 0000000000000000000000000000000000000000..7f5671a3e38b452f70eab46bd6256193d4e48b6f GIT binary patch literal 952 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zK-vS0-A-oPfdtD69Mgd`SU*F|v9*U87?>VgTZ-DD-SKl*FgY`v2)WsX5i3y>~~gGp?v<5jgpM`)!>yxru+QgkK6hkGFFB7qI_^ zszJQQ&Eoel&o_1k&Xc-#dO7Ran83>%ywdwp7c=f!RruOFrY5oBvT%QgEYtFHbvc$b zbAz?OPzwz8t@4tvp$-U#B&gf{H+t-Ai75Dn~2q?PWec{qXX(mbXE5d|_6m{OLtb59owEVgIwNRd%J$Q7_|kzmxSTZ{=Bk1t%- z{1~%h`@g?oXG&-86<)Z6cY~UeQNm$?nzO&=Z0m z@u$&bb9d-0t=2-Geb?5Q+V0uS$CS$vJ?piobHqx)YqboswwkGLGJJAnW@3j^R8@57 zEeQtm`a4O*#t)_k9q_ujA(C?iSG({12ip}^gjD`Jsbf^XB7Tmo4ri9#zQT_|la_^i z;VCir=_1a)*>jhzW9X5Hox(}4nyMm=wmmlsp6q_q-qFkd?2Q9=&!1R)n{U(Ku8HlB zm)N$izHhd(Y_VIZqp+#&wbmb2cKZF^KBym#S7 zshl+@ey@M?c<1uZ){ATMXWol`vEc2yqgI?55^wT#b9Ns($$s7P|06-58D-O7#+?!O zD*N@yD84qFO=14)M_*j>jz7BpgZpQp-KPm%4-NuTzG{hUL`h0wNvc(HQ7VvPFfuT( z)HO8HH8Kk^G_*1@ure^#H88g_FxcHw?1G{pH$NpatrA6pB~YD}feAzdujKq&Kn)C@ Lu6{1-oD!Mj literal 0 HcmV?d00001 diff --git a/resources/recipes/columbusdispatch.recipe b/resources/recipes/columbusdispatch.recipe new file mode 100644 index 0000000000..e021f55048 --- /dev/null +++ b/resources/recipes/columbusdispatch.recipe @@ -0,0 +1,80 @@ +from calibre.web.feeds.news import BasicNewsRecipe + +class ColumbusDispatchRecipe(BasicNewsRecipe): + __license__ = 'GPL v3' + __author__ = 'kwetal' + language = 'en' + version = 1 + + title = u'The Columbus Dispatch' + publisher = u'The Columbus Dispatch' + category = u'News, Newspaper' + description = u'Daily newspaper from central Ohio' + + use_embedded_content = False + remove_empty_feeds = True + oldest_article = 1.2 + max_articles_per_feed = 100 + + no_stylesheets = True + remove_javascript = True + encoding = 'utf-8' + # Seems to work best, but YMMV + simultaneous_downloads = 2 + + # Feeds from http://www.dispatch.com/live/content/rss/index.html + feeds = [] + feeds.append((u'News: Local and state news', u'http://www.dispatch.com/live/static/crt/2_rss_localnews.xml')) + feeds.append((u'News: National news', u'http://www.dispatch.com/live/static/crt/2_rss_nationalnews.xml')) + feeds.append((u'News: Editorials', u'http://www.dispatch.com/live/static/crt/2_rss_editorials.xml')) + feeds.append((u'News: Columnists', u'http://www.dispatch.com/live/static/crt/2_rss_columnists.xml')) + feeds.append((u'News: Health news', u'http://www.dispatch.com/live/static/crt/2_rss_health.xml')) + feeds.append((u'News: Science news', u'http://www.dispatch.com/live/static/crt/2_rss_science.xml')) + feeds.append((u'Sports: OSU football', u'http://www.dispatch.com/live/static/crt/2_rss_osufootball.xml')) + feeds.append((u'Sports: OSU men\'s basketball', u'http://www.dispatch.com/live/static/crt/2_rss_osumensbball.xml')) + feeds.append((u'Sports: OSU women\'s basketball', u'http://www.dispatch.com/live/static/crt/2_rss_osuwomensbball.xml')) + feeds.append((u'Sports: OSU sports', u'http://www.dispatch.com/live/static/crt/2_rss_osusports.xml')) + feeds.append((u'Sports: Blue Jackets', u'http://www.dispatch.com/live/static/crt/2_rss_bluejackets.xml')) + feeds.append((u'Sports: Crew', u'http://www.dispatch.com/live/static/crt/2_rss_crew.xml')) + feeds.append((u'Sports: Clippers', u'http://www.dispatch.com/live/static/crt/2_rss_clippers.xml')) + feeds.append((u'Sports: Indians', u'http://www.dispatch.com/live/static/crt/2_rss_indians.xml')) + feeds.append((u'Sports: Reds', u'http://www.dispatch.com/live/static/crt/2_rss_reds.xml')) + feeds.append((u'Sports: Golf', u'http://www.dispatch.com/live/static/crt/2_rss_golf.xml')) + feeds.append((u'Sports: Outdoors', u'http://www.dispatch.com/live/static/crt/2_rss_outdoors.xml')) + feeds.append((u'Sports: Cavs/NBA', u'http://www.dispatch.com/live/static/crt/2_rss_cavaliers.xml')) + feeds.append((u'Sports: High Schools', u'http://www.dispatch.com/live/static/crt/2_rss_highschools.xml')) + feeds.append((u'Sports: Browns', u'http://www.dispatch.com/live/static/crt/2_rss_browns.xml')) + feeds.append((u'Sports: Bengals', u'http://www.dispatch.com/live/static/crt/2_rss_bengals.xml')) + feeds.append((u'Sports: Auto Racing', u'http://www.dispatch.com/live/static/crt/2_rss_autoracing.xml')) + feeds.append((u'Business News', u'http://www.dispatch.com/live/static/crt/2_rss_business.xml')) + feeds.append((u'Features: Weekender', u'http://www.dispatch.com/live/static/crt/2_rss_weekender.xml')) + feeds.append((u'Features: Life and Arts', u'http://www.dispatch.com/live/static/crt/2_rss_lifearts.xml')) + feeds.append((u'Features: Food', u'http://www.dispatch.com/live/static/crt/2_rss_food.xml')) + feeds.append((u'Features: NOW! for kids', u'http://www.dispatch.com/live/static/crt/2_rss_now.xml')) + feeds.append((u'Features: Travel', u'http://www.dispatch.com/live/static/crt/2_rss_travel.xml')) + feeds.append((u'Features: Home and Garden', u'http://www.dispatch.com/live/static/crt/2_rss_homegarden.xml')) + feeds.append((u'Features: Faith and Values', u'http://www.dispatch.com/live/static/crt/2_rss_faithvalues.xml')) + #feeds.append((u'', u'')) + + keep_only_tags = [] + keep_only_tags.append(dict(name = 'div', attrs = {'class': 'colhed'})) + keep_only_tags.append(dict(name = 'div', attrs = {'class': 'hed'})) + keep_only_tags.append(dict(name = 'div', attrs = {'class': 'subhed'})) + keep_only_tags.append(dict(name = 'div', attrs = {'class': 'date'})) + keep_only_tags.append(dict(name = 'div', attrs = {'class': 'byline'})) + keep_only_tags.append(dict(name = 'div', attrs = {'class': 'srcline'})) + keep_only_tags.append(dict(name = 'div', attrs = {'class': 'body'})) + + remove_tags = [] + remove_tags.append(dict(name = 'div', attrs = {'id': 'middle-story-ad-container'})) + + extra_css = ''' + body {font-family:verdana,arial,helvetica,geneva,sans-serif ;} + a {text-decoration: none; color: blue;} + div.colhed {font-weight: bold;} + div.hed {font-size: xx-large; font-weight: bold; margin-bottom: 0.2em;} + div.subhed {font-size: large;} + div.date {font-size: x-small; font-style: italic; color: #666666; margin-top: 0.4em; margin-bottom: 0.4em;} + div.byline, div.srcline {font-size: small; color: #696969;} + ''' + diff --git a/src/calibre/devices/usbobserver/Makefile b/src/calibre/devices/usbobserver/Makefile index ee98e75bd6..dc14d4ac8d 100644 --- a/src/calibre/devices/usbobserver/Makefile +++ b/src/calibre/devices/usbobserver/Makefile @@ -2,11 +2,7 @@ usbobserver.so : usbobserver.o gcc -arch i386 -arch ppc -bundle usbobserver.o -o usbobserver.so -framework Python -framework IOKit -framework CoreFoundation usbobserver.o : usbobserver.c - gcc -arch i386 -arch ppc -dynamic -I/Library/Frameworks/Python.framework/Versions/2.5/include/python2.5 -c usbobserver.c -o usbobserver.o - - -install : usbobserver.so - cp usbobserver.so /Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/ + gcc -arch i386 -arch ppc -dynamic -I/Library/Frameworks/Python.framework/Versions/Current/Headers -c usbobserver.c -o usbobserver.o clean : rm -f *.o *.so diff --git a/src/calibre/devices/usbobserver/usbobserver.c b/src/calibre/devices/usbobserver/usbobserver.c index a6238f1005..ad30ad6e53 100644 --- a/src/calibre/devices/usbobserver/usbobserver.c +++ b/src/calibre/devices/usbobserver/usbobserver.c @@ -26,28 +26,34 @@ #include #include +#include #include +CFStringRef USB_PROPS[3] = { CFSTR("USB Vendor Name"), CFSTR("USB Product Name"), CFSTR("USB Serial Number") }; + +static PyObject* +get_iokit_string_property(io_service_t dev, int prop) { + CFTypeRef PropRef; + char buf[500]; + + PropRef = IORegistryEntryCreateCFProperty(dev, USB_PROPS[prop], kCFAllocatorDefault, 0); + if (PropRef) { + if(!CFStringGetCString(PropRef, buf, 500, kCFStringEncodingUTF8)) buf[0] = '\0'; + } else buf[0] = '\0'; + + return PyUnicode_DecodeUTF8(buf, strlen(buf), "replace"); +} + static PyObject * usbobserver_get_usb_devices(PyObject *self, PyObject *args) { - mach_port_t masterPort; CFMutableDictionaryRef matchingDict; kern_return_t kr; - /* Create a master port for communication with IOKit */ - kr = IOMasterPort(MACH_PORT_NULL, &masterPort); - - if (kr || !masterPort) { - PyErr_SetString(PyExc_RuntimeError, "Couldn't create master IOKit port"); - return NULL; - } - //Set up matching dictionary for class IOUSBDevice and its subclasses matchingDict = IOServiceMatching(kIOUSBDeviceClassName); if (!matchingDict) { PyErr_SetString(PyExc_RuntimeError, "Couldn't create a USB matching dictionary"); - mach_port_deallocate(mach_task_self(), masterPort); return NULL; } @@ -58,12 +64,12 @@ usbobserver_get_usb_devices(PyObject *self, PyObject *args) { SInt32 score; IOUSBDeviceInterface182 **dev = NULL; UInt16 vendor, product, bcd; + PyObject *manufacturer, *productn, *serial; PyObject *devices, *device; devices = PyList_New(0); if (devices == NULL) { PyErr_NoMemory(); - mach_port_deallocate(mach_task_self(), masterPort); return NULL; } @@ -85,7 +91,15 @@ usbobserver_get_usb_devices(PyObject *self, PyObject *args) { kr = (*dev)->GetDeviceVendor(dev, &vendor); kr = (*dev)->GetDeviceProduct(dev, &product); kr = (*dev)->GetDeviceReleaseNumber(dev, &bcd); - device = Py_BuildValue("(iii)", vendor, product, bcd); + + manufacturer = get_iokit_string_property(usbDevice, 0); + if (manufacturer == NULL) manufacturer = Py_None; + productn = get_iokit_string_property(usbDevice, 1); + if (productn == NULL) productn = Py_None; + serial = get_iokit_string_property(usbDevice, 2); + if (serial == NULL) serial = Py_None; + + device = Py_BuildValue("(iiiOOO)", vendor, product, bcd, manufacturer, productn, serial); if (device == NULL) { IOObjectRelease(usbDevice); (*plugInInterface)->Release(plugInInterface); @@ -109,11 +123,7 @@ usbobserver_get_usb_devices(PyObject *self, PyObject *args) { Py_DECREF(device); } - - //Finished with master port - mach_port_deallocate(mach_task_self(), masterPort); - - return Py_BuildValue("N", devices); + return devices; } static PyMethodDef usbobserver_methods[] = {