Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

minor refactoring, lan/udp resolver implemented as process too

  • Loading branch information...
commit faf3e891f0c93bfca93a3c3250c36ea78881513f 1 parent b3898d4
@RJ authored
View
2  etc/demo-resolver.php
@@ -72,7 +72,7 @@ function get_matches($rq){
// settings for this resolver, reported when we start:
function get_settings(){
$s = new stdclass;
- $s->settings = true;
+ $s->_msgtype = "settings";
$s->name = "php resolver script";
$s->targettime = 15; // fast atm, it's all hardcoded.
$s->weight = 80; // 1-100. higher means preferable.
View
2  etc/seeqpod-resolver.py
@@ -72,7 +72,7 @@ def resolve(artist, track):
####################################################################### settings
settings = dict()
-settings["settings"] = True
+settings["_msgtype"] = "settings"
settings["name"] = "SeeqPod Resolver (Python 2.6)"
settings["targettime"] = 1000 # millseconds
settings["weight"] = 50 # seeqpod results aren't as good as friend's results
View
26 includes/playdar/playable_item.hpp
@@ -3,6 +3,7 @@
#include "playdar/config.hpp"
#include "playdar/streaming_strategy.h"
#include "playdar/types.h"
+#include "playdar/ss_http.hpp"
#include "json_spirit/json_spirit.h"
#include <cassert>
/*
@@ -34,7 +35,6 @@ class PlayableItem
set_mimetype("text/plain");
set_preference(1.0);
set_source("unspecified");
- //set_url("NO_URL");
}
~PlayableItem()
@@ -44,7 +44,7 @@ class PlayableItem
static boost::shared_ptr<PlayableItem> from_json(json_spirit::Object resobj)
{
- string artist, album, track, sid, source, mimetype;
+ string artist, album, track, sid, source, mimetype, url;
int size, bitrate, duration = 0;
float score = 0;
@@ -64,6 +64,9 @@ class PlayableItem
if(resobj_map.find("sid")!=resobj_map.end())
sid = resobj_map["sid"].get_str();
+ if(resobj_map.find("url")!=resobj_map.end())
+ url = resobj_map["url"].get_str();
+
if(resobj_map.find("source")!=resobj_map.end())
source = resobj_map["source"].get_str();
@@ -103,6 +106,7 @@ class PlayableItem
if(bitrate) pip->set_bitrate(bitrate);
if(duration) pip->set_duration(duration);
if(score) pip->set_score(score);
+ if(url.length()) pip->set_url(url);
return pip;
}
@@ -120,7 +124,7 @@ class PlayableItem
j.push_back( Pair("mimetype", mimetype()) );
j.push_back( Pair("bitrate", bitrate()) );
j.push_back( Pair("duration", duration()) );
- //j.push_back( Pair("url", sid_to_url(id())) );
+ j.push_back( Pair("url", url()) );
j.push_back( Pair("score", (double)score()) );
j.push_back( Pair("preference", (double)preference()) );
return j;
@@ -141,7 +145,7 @@ class PlayableItem
void set_artist(string s) { m_artist = s; }
void set_album(string s) { m_album = s; }
void set_track(string s) { m_track = s; }
- //void set_url(string s) { m_url = s; }
+ void set_url(string s) { m_url = s; }
void set_source(string s) { m_source = s; }
void set_mimetype(string s) { m_mimetype = s; }
void set_duration(int s) { m_duration = s; }
@@ -162,7 +166,17 @@ class PlayableItem
}
// getters
- boost::shared_ptr<StreamingStrategy> streaming_strategy() const { return m_ss; }
+ boost::shared_ptr<StreamingStrategy> streaming_strategy() const
+ {
+ // TODO (make this mutable and call set_ss on first call?)
+ if(m_ss) return m_ss;
+ if(!m_ss && m_url.length())
+ {
+ return boost::shared_ptr<StreamingStrategy>
+ (new HTTPStreamingStrategy(m_url));
+ }
+ return m_ss; // would be null if not given.
+ }
void set_id(string s) { m_uuid = s; }
@@ -171,6 +185,7 @@ class PlayableItem
const string & track() const { return m_track; }
const string & source() const { return m_source; }
const string & mimetype() const { return m_mimetype; }
+ const string & url() const { return m_url; }
const float score() const { return m_score; }
const int duration() const { return m_duration; }
const int bitrate() const { return m_bitrate; }
@@ -185,6 +200,7 @@ class PlayableItem
string m_album;
string m_track;
string m_mimetype;
+ string m_url;
int m_size;
int m_duration;
int m_bitrate;
View
91 includes/playdar/playdar_resolver_process.hpp
@@ -0,0 +1,91 @@
+/*
+ This header is a helper for any external resolver written in c++
+ It handles communicating with playdar over stdio.
+*/
+#include <boost/asio.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/asio.hpp>
+#include <boost/thread.hpp>
+#include <stdio.h>
+#include <iostream>
+#include <map>
+#include <string>
+
+#include "json_spirit/json_spirit.h"
+#include "playdar/resolver_query.hpp"
+#include "playdar/playable_item.hpp"
+
+#define MAXBUF 4096 // max size of msg payload
+
+using namespace std;
+using namespace json_spirit;
+
+set< query_uid > dispatched_qids; // qids we already searched for.
+
+// send a msg back to playdar app
+// it takes a JSON val, and prepends the frame (4 byte length indicator)
+void playdar_write( Value v )
+{
+ ostringstream os;
+ write_formatted( v, os );
+ string msg = os.str();
+ boost::uint32_t len = htonl(msg.length());
+ cout.write( (char*)&len, 4 );
+ cout.write( msg.data(), msg.length() );
+ cout.flush();
+}
+
+// ask if we should dispatch this query (checks if we've already seen it etc)
+bool playdar_should_dispatch( query_uid qid )
+{
+ if(dispatched_qids.find(qid)!=dispatched_qids.end())
+ {
+ //cerr << "Skipping dispatch, already seen qid " << rq->id() << endl;
+ return false;
+ }else{
+ dispatched_qids.insert( qid );
+ return true;
+ }
+}
+
+// tell playdar to start resolving this query
+void playdar_dispatch( rq_ptr rq )
+{
+ Object o;
+ o.push_back( Pair("_msgtype", "query") );
+ o.push_back( Pair("query", rq->get_json()) );
+ playdar_write( o );
+}
+
+
+// tell playdar we found a result for something
+void playdar_report_results( query_uid qid, vector< pi_ptr > results )
+{
+ cerr << "Reporting results (not) " << endl;
+ Object o;
+ o.push_back( Pair("_msgtype", "results") );
+ o.push_back( Pair("qid", qid) );
+ Array arr;
+ BOOST_FOREACH( pi_ptr pip, results )
+ {
+ arr.push_back( pip->get_json() );
+ }
+ o.push_back( Pair("results", arr) );
+ playdar_write( o );
+}
+
+// report settings about this resolver
+void playdar_send_settings( const string& name, int weight, int targettime )
+{
+ Object o;
+ o.push_back( Pair("_msgtype", "settings") );
+ o.push_back( Pair("name", name) );
+ o.push_back( Pair("weight", weight) );
+ o.push_back( Pair("targettime", targettime) );
+ playdar_write( o );
+}
+
+
+
+
View
4 includes/playdar/rs_script.h
@@ -58,12 +58,14 @@ class rs_script : public ResolverService
void init_worker();
void process_output();
+ void process_stderr();
bool m_dead;
bool m_got_settings;
string m_scriptpath;
bp::child * m_c;
- boost::thread * m_t;
+ boost::thread * m_t; // std out (main comms)
+ boost::thread * m_e; // std error (logging)
bp::postream * m_os;
bool m_exiting;
View
2  includes/playdar/ss_http.hpp
@@ -1,7 +1,7 @@
#ifndef __HTTP_STRAT_H__
#define __HTTP_STRAT_H__
#include <boost/asio.hpp>
-
+#include "playdar/streaming_strategy.h"
using namespace boost::asio::ip;
/*
Consider this a nasty hack until I find a decent c++ http library
View
45 resolver-ext/lan/CMakeLists.txt
@@ -0,0 +1,45 @@
+PROJECT(lanresolver)
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6 FATAL_ERROR)
+
+SET(PLAYDAR_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../")
+SET(CMAKE_MODULE_PATH "${PLAYDAR_PATH}/CMakeModules")
+SET(DEPS "${PLAYDAR_PATH}/deps")
+
+FIND_PACKAGE(Boost 1.35 REQUIRED COMPONENTS filesystem system regex thread program_options)
+FIND_PACKAGE(OsspUuid REQUIRED)
+
+INCLUDE_DIRECTORIES(
+ ${DEPS}/json_spirit_v3.00 # json parser, using boost spirit
+ ${PLAYDAR_PATH}/includes # playdar includes
+ ${OSSPUUID_INCLUDE_DIR}
+ ${Boost_INCLUDE_DIR}
+ /usr/local/include
+ )
+
+# Always check local/lib first:
+LINK_DIRECTORIES(/usr/local/lib)
+
+SET(CMAKE_VERBOSE_MAKEFILE ON)
+INCLUDE(InstallRequiredSystemLibraries)
+
+#add definitions, compiler switches, etc.
+ADD_DEFINITIONS(-Wall -ggdb)
+
+# PDL doesn't know apple mac = posix, this tells it:
+IF(APPLE)
+ ADD_DEFINITIONS(-Dunix)
+ENDIF(APPLE)
+
+ADD_EXECUTABLE(lanresolver
+ main.cpp
+ # json parser:
+ ${DEPS}/json_spirit_v3.00/json_spirit/json_spirit_reader.cpp
+ ${DEPS}/json_spirit_v3.00/json_spirit/json_spirit_value.cpp
+ ${DEPS}/json_spirit_v3.00/json_spirit/json_spirit_writer.cpp
+ )
+TARGET_LINK_LIBRARIES(lanresolver
+ ${OSSPUUID_LIBRARIES} # BSD-like
+ ${Boost_SYSTEM_LIBRARY}
+ ${Boost_THREAD_LIBRARY}
+ )
+
View
3  resolver-ext/lan/README.txt
@@ -0,0 +1,3 @@
+Took the lan/udp resolver and moved it into an external process:
+Broadcasts searches on the LAN using UDP multicast.
+Streams results using normal HTTP requests.
View
337 resolver-ext/lan/main.cpp
@@ -0,0 +1,337 @@
+#include "playdar/playdar_resolver_process.hpp"
+
+// funcs
+bool process_msg( const string & msg );
+void run();
+void async_send(boost::asio::ip::udp::endpoint * remote_endpoint, const string& message);
+void handle_send(const boost::system::error_code& error, size_t bytes_recvd, char * scratch );
+void handle_receive_from(const boost::system::error_code& error, size_t bytes_recvd);
+void report_results( query_uid qid, boost::shared_ptr<PlayableItem> pip );
+void send_response( query_uid qid, pi_ptr pip, boost::asio::ip::udp::endpoint sep );
+void broadcast_search( rq_ptr rq, rq_callback_t cb );
+
+// global vars
+char data_[MAXBUF];
+boost::asio::ip::udp::socket * socket_;
+boost::asio::ip::udp::endpoint sender_endpoint_;
+boost::asio::ip::udp::endpoint * broadcast_endpoint_;
+boost::asio::io_service * io_service;
+boost::thread * responder_thread;
+
+map< query_uid, rq_callback_t > qid_handlers; // handler functions for PIs returned by playdar by QID
+
+//
+int main(int argc, char **argv)
+{
+ cerr << "External UDP LAN Resolver says hello." << endl;
+
+ playdar_send_settings( "UDP Ext Resolver", 99, 50 );
+
+ // init UDP multicast stuff:
+ broadcast_endpoint_ =
+ new boost::asio::ip::udp::endpoint
+ ( boost::asio::ip::address::from_string
+ (/*conf()->get<string> ("plugins.lan_udp.multicast")*/"239.255.0.1"),
+ /*conf()->get<int>("plugins.lan_udp.port")*/ 8888);
+ responder_thread = new boost::thread(&run);
+
+
+ // enter main loop for handling stdin:
+ char buffer[MAXBUF];
+ boost::uint32_t len;
+ while( !cin.fail() && !cin.eof() )
+ {
+ // get length header:
+ cin.read( (char*)&len, 4 );
+ if(cin.fail() || cin.eof())
+ {
+ cerr << "Stdin stream failed" << endl;
+ return 1;
+ }
+ len = ntohl(len);
+ if(len > MAXBUF)
+ {
+ cerr << "Payload length header too big! (" << len << ")" << endl;
+ return 2;
+ }
+ // get msg payload:
+ cin.read( (char*)&buffer, len );
+ if(cin.fail() || cin.eof())
+ {
+ cerr << "Stdin stream failed" << endl;
+ return 1;
+ }
+ string msg( (char*)&buffer, len );
+ if(!process_msg( msg )) break;
+ }
+
+ cerr << "Bailed from main loop due to error. Exiting." << endl;
+ // cleanup:
+ io_service->stop();
+ responder_thread->join();
+ delete(socket_);
+ delete(broadcast_endpoint_);
+ return 99;
+}
+
+bool process_msg( const string& msg )
+{
+ cerr << "Process msg:" << msg << endl << endl;
+ Value j;
+ if(!read(msg, j) || j.type() != obj_type)
+ {
+ cerr << "Aborting, invalid JSON." << endl;
+ return false;
+ }
+ Object o = j.get_obj();
+ map<string, Value> m;
+ obj_to_map(o, m);
+ if(m.find("artist")!=m.end()) // it's a query TODO this sucks
+ {
+ rq_ptr rq;
+ try
+ {
+ rq = ResolverQuery::from_json(o);
+ // dispatch query. will be dropped if qid already exists
+ rq_callback_t cb = boost::bind(&report_results, _1, _2);
+ broadcast_search( rq, cb );
+ return true;
+ }
+ catch(...)
+ {
+ cerr << "Invalid query input from playdar" << endl;
+ return false;
+ }
+ }
+
+ cerr << "Unhandled msg rcvd from playdar." << endl;
+ return true;
+
+}
+
+// tell playdar to start searching for something
+void broadcast_search( rq_ptr rq, rq_callback_t cb )
+{
+ if(!playdar_should_dispatch( rq->id() )) return;
+ // register callback if we get results for this qid:
+ if(cb) qid_handlers[rq->id()] = cb;
+ cerr << "Dispatching (" << rq->from_name() << "):\t" << rq->str() << endl;
+ // send UDP search message:
+ Object jq;
+ jq.push_back( Pair("from_name", "ext udp script TODO"/*conf()->name()*/) );
+ jq.push_back( Pair("query", rq->get_json()) );
+ ostringstream querystr;
+ write_formatted( jq, querystr );
+ async_send(broadcast_endpoint_, querystr.str());
+}
+
+// run thread for UDP stuff
+// sets up socket, joins multicast UDP group, listens for UDP msg.
+// called in a thread, it calls io_service->run() so never returns.
+void run()
+{
+ io_service = new boost::asio::io_service;
+ socket_ = new boost::asio::ip::udp::socket(*io_service);
+ // Create the socket so that multiple may be bound to the same address.
+ boost::asio::ip::udp::endpoint listen_endpoint( boost::asio::ip::address::from_string("0.0.0.0"), 8888);
+ socket_->open(listen_endpoint.protocol());
+ socket_->set_option(boost::asio::ip::udp::socket::reuse_address(true));
+ socket_->bind(listen_endpoint);
+ // Join the multicast group.
+ socket_->set_option( boost::asio::ip::multicast::join_group(
+ boost::asio::ip::address::from_string("239.255.0.1")));
+ socket_->async_receive_from(
+ boost::asio::buffer(data_, MAXBUF), sender_endpoint_,
+ boost::bind(&handle_receive_from,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ // now we're listening.
+ cerr << "DL UDP Resolver is online udp://"
+ << socket_->local_endpoint().address() << ":"
+ << socket_->local_endpoint().port()
+ << endl;
+ // announce our presence to the LAN:
+ string hello = "OHAI ";
+ hello += "TODOname"; //conf()->name();
+ async_send(broadcast_endpoint_, hello);
+ io_service->run();
+ // won't get here, io_service will run forever.
+}
+
+
+// called when we rcv a UDP msg
+void handle_receive_from(const boost::system::error_code& error, size_t bytes_recvd)
+{
+ if (!error)
+ {
+ std::ostringstream msgs;
+ msgs.write(data_, bytes_recvd);
+ std::string msg = msgs.str();
+
+ boost::asio::ip::address sender_address = sender_endpoint_.address();
+
+ do
+ {
+ //cerr << "LAN_UDP: Received multicast message (from "
+ // << sender_address.to_string() << ":" << sender_endpoint_.port() << "):"
+ // << msg << endl;
+
+ // join leave msg, for debugging on lan
+ if(msg.substr(0,5)=="OHAI " || msg.substr(0,8)=="KTHXBYE ")
+ {
+ cerr << "INFO Presence msg: " << msg << endl;
+ break;
+ }
+
+ // try and parse it as json:
+ Value mv;
+ if(!read(msg, mv))
+ {
+ cerr << "LAN_UDP: invalid JSON in this message, discarding." << endl;
+ break; // Invalid JSON, ignore it.
+ }
+ Object qo = mv.get_obj();
+ map<string,Value> r;
+ obj_to_map(qo,r);
+
+ if(r.find("query")!=r.end()) // REQUEST / NEW QUERY
+ {
+ Object qryobj = r["query"].get_obj();
+ boost::shared_ptr<ResolverQuery> rq;
+ try
+ {
+ rq = ResolverQuery::from_json(qryobj);
+ }
+ catch (...)
+ {
+ cerr << "LAN_UDP: missing fields in JSON query object, discarding" << endl;
+ break;
+ }
+
+ // dispatch query to playdar if it's not already running:
+ if(playdar_should_dispatch(rq->id()))
+ {
+ qid_handlers[rq->id()] = boost::bind(&send_response, _1, _2, sender_endpoint_);
+ playdar_dispatch( rq );
+ }
+ }
+ else if(r.find("qid")!=r.end()) // RESPONSE
+ {
+ Object resobj = r["result"].get_obj();
+ map<string,Value> resobj_map;
+ obj_to_map(resobj, resobj_map);
+ query_uid qid = r["qid"].get_str();
+ // if we could ask "query_exists?" we could abort if it doesnt at this point.
+ //cerr << "LAN_UDP: Got udp response." <<endl;
+ boost::shared_ptr<PlayableItem> pip;
+ try
+ {
+ pip = PlayableItem::from_json(resobj);
+ }
+ catch (...)
+ {
+ cerr << "LAN_UDP: Missing fields in response json, discarding" << endl;
+ break;
+ }
+ ostringstream rbs;
+ rbs << "http://"
+ << sender_endpoint_.address()
+ << ":"
+ << sender_endpoint_.port();
+ string url = rbs.str();
+ url += "/sid/";
+ url += pip->id();
+ pip->set_url( url );
+ // anything on udp multicast must be pretty fast:
+ pip->set_preference((float)0.9);
+ vector< boost::shared_ptr<PlayableItem> > v;
+ v.push_back(pip);
+ playdar_report_results(qid, v);
+ cerr << "INFO Result from '" << pip->source()
+ <<"' for '"<< pip->artist() <<"' - '"
+ << pip->track() << "' [score: "<< pip->score() <<"]"
+ << endl;
+ }
+
+ }while(false);
+
+ socket_->async_receive_from(
+ boost::asio::buffer(data_, MAXBUF), sender_endpoint_,
+ boost::bind(&handle_receive_from,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ else
+ {
+ cerr << "Some error for udp" << endl;
+ }
+}
+
+void
+send_response( query_uid qid,
+ boost::shared_ptr<PlayableItem> pip,
+ boost::asio::ip::udp::endpoint sep )
+{
+ cerr << "LAN_UDP responding for " << qid << " to: "
+ << sep.address().to_string()
+ << " score: " << pip->score()
+ << endl;
+ Object response;
+ response.push_back( Pair("qid", qid) );
+ Object result = pip->get_json();
+ response.push_back( Pair("result", result) );
+ ostringstream ss;
+ write_formatted( response, ss );
+ async_send(&sep, ss.str());
+}
+
+
+void
+report_results( query_uid qid,
+ boost::shared_ptr<PlayableItem> pip )
+{
+ cerr << "Report result for " << qid << " : "
+ << " score: " << pip->score()
+ << endl;
+ Object o;
+ o.push_back( Pair("_msgtype", "results") );
+ o.push_back( Pair("qid", qid) );
+ Array arr;
+ arr.push_back( pip->get_json() );
+ o.push_back( Pair("results", arr) );
+
+ playdar_write( o );
+}
+
+
+void
+async_send(boost::asio::ip::udp::endpoint * remote_endpoint, const string& message)
+{
+ if(message.length()>1200)
+ {
+ cerr << "WARNING outgoing UDP message is rather large, haven't tested this, discarding." << endl;
+ return;
+ }
+ //cerr << "UDPsend[" << remote_endpoint->address().to_string()
+ // << ":" << remote_endpoint->port() << "]"
+ // << "(" << message << ")" << endl;
+ char * buf = (char*)malloc(message.length());
+ memcpy(buf, message.data(), message.length());
+ socket_->async_send_to(
+ boost::asio::buffer(buf,message.length()),
+ *remote_endpoint,
+ boost::bind(&handle_send,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred,
+ buf));
+}
+
+void handle_send(const boost::system::error_code& error, size_t bytes_recvd, char * scratch )
+{
+ // free the memory that was holding the message we just sent.
+ if(scratch)
+ {
+ free(scratch);
+ }
+}
+
View
70 src/rs_script.cpp
@@ -146,16 +146,25 @@ rs_script::init_worker()
bp::context ctx;
ctx.stdout_behavior = bp::capture_stream();
ctx.stdin_behavior = bp::capture_stream();
-// ctx.stderr_behavior = bp::capture_stream();
+ ctx.stderr_behavior = bp::capture_stream();
bp::child c = bp::launch(m_scriptpath, args, ctx);
m_c = new bp::child(c);
m_os = & c.get_stdin();
- m_t = new boost::thread(
- boost::bind(&rs_script::process_output,
- this));
+ m_t = new boost::thread( boost::bind(&rs_script::process_output, this) );
+ m_e = new boost::thread( boost::bind(&rs_script::process_stderr, this) );
}
+void
+rs_script::process_stderr()
+{
+ bp::pistream &is = m_c->get_stderr();
+ string line;
+ while (!is.fail() && !is.eof() && getline(is, line))
+ {
+ cerr << name() << ":\t" << line << endl;
+ }
+}
// runs forever processing output of script
void
@@ -192,8 +201,17 @@ rs_script::process_output()
map<string,Value> rr;
obj_to_map(ro,rr);
// msg will either be a query result, or a settings object
- if( rr.find("settings")!=rr.end() &&
- rr["settings"].get_bool())
+ if( rr.find("_msgtype")==rr.end() ||
+ rr["_msgtype"].type() != str_type )
+ {
+ cerr << "No string _msgtype property of JSON object. error." << endl;
+ continue;
+ }
+
+ string msgtype = rr["_msgtype"].get_str();
+
+ // initial resolver settings being reported:
+ if(msgtype == "settings")
{
if( rr.find("weight") != rr.end() &&
rr["weight"].type() == int_type )
@@ -219,26 +237,30 @@ rs_script::process_output()
m_cond_settings.notify_one();
continue;
}
- // must be a query result:
- query_uid qid = rr["qid"].get_str();
- Array resultsA = rr["results"].get_array();
- vector< boost::shared_ptr<PlayableItem> > v;
- BOOST_FOREACH(Value & result, resultsA)
+
+ // a query result:
+ if(msgtype == "results")
{
- Object po = result.get_obj();
- boost::shared_ptr<PlayableItem> pip;
- pip = PlayableItem::from_json(po);
- cout << "Parserd pip from script: " << endl;
- write_formatted( pip->get_json(), cout );
- map<string,Value> po_map;
- obj_to_map(po, po_map);
- string url = po_map["url"].get_str();
- cout << "url=" << url << endl;
- boost::shared_ptr<StreamingStrategy> s(new HTTPStreamingStrategy(url));
- pip->set_streaming_strategy(s);
- v.push_back(pip);
+ query_uid qid = rr["qid"].get_str();
+ Array resultsA = rr["results"].get_array();
+ vector< boost::shared_ptr<PlayableItem> > v;
+ BOOST_FOREACH(Value & result, resultsA)
+ {
+ Object po = result.get_obj();
+ boost::shared_ptr<PlayableItem> pip;
+ pip = PlayableItem::from_json(po);
+ cout << "Parserd pip from script: " << endl;
+ write_formatted( pip->get_json(), cout );
+ map<string,Value> po_map;
+ obj_to_map(po, po_map);
+ string url = po_map["url"].get_str();
+ cout << "url=" << url << endl;
+ boost::shared_ptr<StreamingStrategy> s(new HTTPStreamingStrategy(url));
+ pip->set_streaming_strategy(s);
+ v.push_back(pip);
+ }
+ report_results(qid, v, name());
}
- report_results(qid, v, name());
}
cout << "Gateway plugin read loop exited" << endl;
m_dead = true;
Please sign in to comment.
Something went wrong with that request. Please try again.