diff options
author | louis <louis.braun@gmx.de> | 2013-04-07 10:39:42 +0200 |
---|---|---|
committer | louis <louis.braun@gmx.de> | 2013-04-07 10:39:42 +0200 |
commit | fba3191de71867e91eb51cde93136fcdda64c0ab (patch) | |
tree | e99221ec2c9a7dc612b7e818c4b544a0c1e65a1d /rssreader.c | |
parent | 518e7e87332e2b53e9f3e5f9fc853abaec2b360f (diff) | |
download | skin-nopacity-fba3191de71867e91eb51cde93136fcdda64c0ab.tar.gz skin-nopacity-fba3191de71867e91eb51cde93136fcdda64c0ab.tar.bz2 |
Added RSS Feed support
Diffstat (limited to 'rssreader.c')
-rw-r--r-- | rssreader.c | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/rssreader.c b/rssreader.c new file mode 100644 index 0000000..d3ff151 --- /dev/null +++ b/rssreader.c @@ -0,0 +1,254 @@ +#include "rssreader.h" + +static size_t WriteXMLMemoryCallback(void* pointer, size_t size, size_t nmemb, void* xmlData) { + size_t realsize = size * nmemb; + struct XMLMemoryStruct* memStruct = (struct XMLMemoryStruct*)xmlData; + if (memStruct->memory) + memStruct->memory = (char*)realloc(memStruct->memory, memStruct->size + realsize + 1); + else + memStruct->memory = (char*)malloc(memStruct->size + realsize + 1); + if (memStruct->memory) { + memcpy (&(memStruct->memory[memStruct->size]), pointer, realsize); + memStruct->size += realsize; + memStruct->memory[memStruct->size] = 0; + } + return realsize; +} + +cRssReader::cRssReader(cOsd *osd, cFont *font, cPoint position, cPoint size) { + this->osd = osd; + this->font = font; + pixmap = NULL; + + x = position.X(); + y = position.Y(); + + width = size.X(); + height = size.Y(); + + xmlData.memory = 0; + xmlData.size = 0; + + useProxy = false; + httpproxy = ""; + + separator = " +++ "; + currentElement = 0; + switchToNextMessage = false; +} + +cRssReader::~cRssReader() { + osd->DestroyPixmap(pixmap); +} + +int cRssReader::readRssURL(const char *url) { + CURL* my_curl_handle; + long code; + if (xmlData.memory) + free(xmlData.memory); + xmlData.memory = 0; + xmlData.size = 0; + if (curl_global_init(CURL_GLOBAL_ALL) != 0) { + esyslog("nopacity: Error, something went wrong with curl_global_init()"); + return -1; + } + my_curl_handle = curl_easy_init(); + if (!my_curl_handle) { + esyslog("nopacity: Error, unable to get handle from curl_easy_init()"); + return -1; + } + if (useProxy) { + curl_easy_setopt(my_curl_handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); + curl_easy_setopt(my_curl_handle, CURLOPT_PROXY, httpproxy.c_str()); // Specify HTTP proxy + } + curl_easy_setopt(my_curl_handle, CURLOPT_URL, url); // Specify URL to get + curl_easy_setopt(my_curl_handle, CURLOPT_FOLLOWLOCATION, 0); // don't follow redirects + curl_easy_setopt(my_curl_handle, CURLOPT_WRITEFUNCTION, WriteXMLMemoryCallback); // Send all data to this function + curl_easy_setopt(my_curl_handle, CURLOPT_WRITEDATA, (void*)&xmlData); // Pass our 'data' struct to the callback function + curl_easy_setopt(my_curl_handle, CURLOPT_MAXFILESIZE, 1024*1024); // Set maximum file size to get (bytes) + curl_easy_setopt(my_curl_handle, CURLOPT_NOPROGRESS, 1); // No progress meter + curl_easy_setopt(my_curl_handle, CURLOPT_NOSIGNAL, 1); // No signaling + curl_easy_setopt(my_curl_handle, CURLOPT_TIMEOUT, 30); // Set timeout to 30 seconds + curl_easy_setopt(my_curl_handle, CURLOPT_USERAGENT, NOPACITY_USERAGENT); // Some servers don't like requests that are made without a user-agent field + + if (curl_easy_perform(my_curl_handle) != 0) { + curl_easy_cleanup(my_curl_handle); // Cleanup curl stuff + if (xmlData.memory) { + free(xmlData.memory); + xmlData.memory = 0; + xmlData.size = 0; + } + esyslog("nopacity: Error, download of '%s' failed", url); + return -1; + } + curl_easy_getinfo(my_curl_handle, CURLINFO_HTTP_CODE, &code); + if (code == 404) { + if (xmlData.memory) + free(xmlData.memory); + xmlData.memory = 0; + xmlData.size = 0; + } + curl_easy_cleanup(my_curl_handle); // Cleanup curl stuff + + return xmlData.size; +} + +void cRssReader::traverseTree(xmlNode * a_node, bool foundItem) { + xmlNode *cur_node = NULL; + xmlChar *node_content; + bool foundItemAct = false; + for (cur_node = a_node; cur_node; cur_node = cur_node->next) { + if (cur_node->type == XML_ELEMENT_NODE) { + if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"item"))){ + foundItemAct = true; + saveItem(); + } else { + if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"title")) && foundItem){ + node_content = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); + if (node_content) + title = (const char *)node_content; + else + title = ""; + xmlFree(node_content); + } + if ((!xmlStrcmp(cur_node->name, (const xmlChar *)"description")) && foundItem){ + node_content = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); + if (node_content) + content = (const char *)node_content; + else + content = ""; + xmlFree(node_content); + } + } + } + traverseTree(cur_node->children, foundItemAct); + } + +} + +void cRssReader::saveItem(void) { + if (!title.length()) + return; + RssElement rssElement; + rssElement.title = title; + rssElement.content = content; + int width = font->Width(title.c_str()) + font->Width(": ") + font->Width(content.c_str()) + font->Width(separator.c_str()); + rssElement.width = width; + rssElements.push_back(rssElement); +} + +void cRssReader::saveRss(void) { + xmlNode *root_element = NULL; + root_element = xmlDocGetRootElement(doc); + traverseTree(root_element, false); + saveItem(); + xmlFreeDoc(doc); +} + +void cRssReader::createPixmap(void) { + if (pixmap) + osd->DestroyPixmap(pixmap); + pixmap = osd->CreatePixmap(7, cRect(x, y, width, height), cRect(0, 0, rssElements[currentElement].width, height)); + pixmap->Fill(clrTransparent); + pixmap->SetAlpha(0); +} + +void cRssReader::drawText(void) { + int currentX = 5; + int textY = (height - font->Height()) / 2; + cString text = cString::sprintf("%s: ", rssElements[currentElement].title.c_str()); + pixmap->DrawText(cPoint(currentX, textY), *text, Theme.Color(clrMenuFontMenuItemHigh), clrTransparent, font); + currentX += font->Width(*text); + text = cString::sprintf("%s%s", rssElements[currentElement].content.c_str(), separator.c_str()); + pixmap->DrawText(cPoint(currentX, textY), *text, Theme.Color(clrMenuFontMenuItem), clrTransparent, font); +} + +void cRssReader::DoSleep(int duration) { + int sleepSlice = 10; + for (int i = 0; Running() && (i*sleepSlice < duration); i++) + cCondWait::SleepMs(sleepSlice); +} + +void cRssReader::Action(void) { + int success = readRssURL(feedUrl.c_str()); + if (success < 1) + return; + if (!strstr(xmlData.memory, "rss")) + return; + doc = NULL; + doc = xmlReadMemory(xmlData.memory, strlen(xmlData.memory), "noname.xml", NULL, 0); + if (doc == NULL) { + return; + } + saveRss(); + + int numElements = rssElements.size(); + int scrollDelay = config.rssScrollDelay * 1000; + int drawPortX; + int FrameTime = config.rssScrollFrameTime; + int maxX; + bool doSleep; + + createPixmap(); + drawText(); + fadeInOut(true); + DoSleep(scrollDelay); + doSleep = false; + maxX = pixmap->DrawPort().Width() - pixmap->ViewPort().Width(); + + while (Running()) { + if (doSleep) { + fadeInOut(true); + DoSleep(scrollDelay); + doSleep = false; + } + uint64_t Now = cTimeMs::Now(); + cPixmap::Lock(); + drawPortX = pixmap->DrawPort().X(); + drawPortX -= 1; + cPixmap::Unlock(); + if ((abs(drawPortX) > maxX) || switchToNextMessage) { + if (!switchToNextMessage) + DoSleep(scrollDelay); + else + switchToNextMessage = false; + fadeInOut(false); + currentElement = (currentElement + 1)%numElements; + createPixmap(); + drawText(); + maxX = pixmap->DrawPort().Width() - pixmap->ViewPort().Width(); + drawPortX = 0; + doSleep = true; + } + cPixmap::Lock(); + if (Running()) + pixmap->SetDrawPortPoint(cPoint(drawPortX, 0)); + cPixmap::Unlock(); + int Delta = cTimeMs::Now() - Now; + if (Running()) + osd->Flush(); + if (Running() && (Delta < FrameTime)) + cCondWait::SleepMs(FrameTime - Delta); + } + +} + +void cRssReader::fadeInOut(bool fadeIn) { + int frameTime = 50; + int alpha = (fadeIn)?0:225; + for (int i=0; i<10; i++) { + if (Running()) { + if (fadeIn) + alpha += 26; + else + alpha -= 26; + if (alpha < 0) alpha = 0; + if (alpha > 255) alpha = 255; + cPixmap::Lock(); + pixmap->SetAlpha(alpha); + cPixmap::Unlock(); + osd->Flush(); + } + DoSleep(frameTime); + } +} |