def post(self, stream_id):


        yield motor.Op(self.db.streams.update,  {"_id":ObjectId(stream_id)},
                       {"$set":{"status": "ready"}}, multi=False)

        stream_obj = yield motor.Op(self.db.streams.find_one, {"_id":ObjectId(stream_id)},
                                    {"pipeline_server": 1, "quality": 1, "_id": 0})

        pr = PipelineRouter(self.db, stream_id)
        server = yield tornado.gen.Task(pr.get_server)

        if "error" in server or server is None:
            server = yield motor.Op(self.db.servers.find_one,
                                      { "type": "pipeline", "level": {"$lte": 9}, "down": False},
                                      {"local_ip":1, "port":1}, sort=[('level', -1)])
        url = pr.get_restart_url(server)

        post_args = {
            "stream": stream_id,
            "quality": min(stream_obj["quality"])
        }

        response = yield tornado.gen.Task(pr.request, url=url, post_args=post_args)

        self.write(response)
        self.finish()
Example #2
0
    def on_metadata(self):
        if "stream_id" in self.metadata:
            pr = PipelineRouter(self.db, self.metadata["stream_id"])
            server = yield tornado.gen.Task(pr.get_server)
            url = pr.get_updates_url(server)

            # websocket.enableTrace(True)
            cache_hash = url + "?stream_id=" + self.metadata["stream_id"]

            if cache_hash in self.settings["ws_cache"]:
                self.client_receiver = self.settings["ws_cache"][cache_hash]
            else:
                # print "vyt"
                client = websocket.create_connection(url)
                # client = yield tornado.gen.Task(websocket.create_connection, url)
                # print "at"
                client.send(json.dumps(self.metadata))
                # print client

                self.client_receiver = ClientWSReceiver(cache_hash, client)
                self.client_receiver.start()
                self.settings["ws_cache"][cache_hash] = self.client_receiver

            self.client_receiver.add_handler(self)
            print(self.metadata)
            if "action" in self.metadata:
                print('send ', self.metadata)
                self.client_receiver.client.send(self.metadata)
Example #3
0
    def on_metadata(self):
        if "stream_id" in self.metadata:
            pr = PipelineRouter(self.db, self.metadata["stream_id"])
            server = yield tornado.gen.Task(pr.get_server)
            url = pr.get_updates_url(server)

            # websocket.enableTrace(True)
            self.client = websocket.create_connection(url)
            self.client.send(json.dumps(self.metadata))

            self.client_receiver = ClientWSReceiver(self)
            self.client_receiver.start()
Example #4
0
    def post(self, stream_id):

        pr = PipelineRouter(self.db, stream_id)
        url = pr.get_terminal_url({
            "local_ip": self.get_argument("local-ip"),
            "port": int(self.get_argument("port"))
        })

        post_args = {
            "command": "use " + stream_id + ";" + self.get_argument("command")
        }

        response = yield tornado.gen.Task(pr.request,
                                          url=url,
                                          post_args=post_args)

        self.write(response)
        self.finish()
Example #5
0
    def on_metadata(self):

        if "stream_id" in self.metadata:

            stream = yield motor.Op(
                self.db.streams.find_one,
                {"_id": ObjectId(self.metadata["stream_id"])}, {
                    "reencoding": 1,
                    "_id": 0
                })

            if stream['reencoding']:

                pr = PipelineRouter(self.db, self.metadata["stream_id"])
                server = yield tornado.gen.Task(pr.get_server)
                url = pr.get_live_url(server)

                # websocket.enableTrace(True)
                self.client = websocket.create_connection(url)
                self.client.send(json.dumps(self.metadata))
            else:
                self.close()
Example #6
0
    def post(self):

        stream_id = self.get_argument("stream-id")
        group_id = self.get_argument("group-id")

        ids = self.request.arguments['group[]'][1:-1]
        artists = self.request.arguments['artist[]']
        title = self.request.arguments['title[]']
        remove = self.request.arguments['remove[]']

        dec_count = 0
        dec = 0

        for i in range(len(ids)):
            try:
                id = ObjectId(ids[i])

            except:
                id = None

            if id is not None:
                if remove[i] == "1":
                    yield motor.Op(self.db.media.update, {
                        "_id": id,
                        "groups.id": group_id
                    }, {"$pull": {
                        "groups": {
                            "id": group_id
                        }
                    }},
                                   upsert=False,
                                   multi=False)

                    group = yield motor.Op(self.db.media.find_one, {"_id": id},
                                           {
                                               "groups": 1,
                                               "file_id": 1,
                                               "size": 1,
                                               "_id": 0
                                           })

                    dec_count += 1
                    dec += group["size"]

                    if len(group["groups"]) == 0:
                        yield motor.Op(self.db.files.remove,
                                       {"_id": ObjectId(group["file_id"])})
                        yield motor.Op(self.db.media.remove, {"_id": id})

                else:
                    set = {
                        "artist": artists[i],
                        "title": title[i],
                        "groups.$.weight": i
                    }
                    yield motor.Op(self.db.media.update, {
                        "_id": id,
                        "groups.id": group_id
                    }, {"$set": set},
                                   upsert=False,
                                   multi=False)

        if dec > 0:
            self.db.users.update({"_id": ObjectId(self.get_current_user())},
                                 {"$dec": {
                                     "size": dec
                                 }},
                                 upsert=False,
                                 multi=False)
            # self.db.streams.update({"_id":ObjectId(stream_id)},
            #                        {"$dec":{"size": group["size"]}}, upsert=False, multi=False)
            self.db.streams.update({"_id": ObjectId(stream_id)},
                                   {"$dec": {
                                       "count": dec_count,
                                       "size": dec
                                   }},
                                   upsert=False,
                                   multi=False)

        stream_obj = yield motor.Op(self.db.streams.find_one,
                                    {"_id": ObjectId(stream_id)}, {
                                        "status": 1,
                                        "pipeline_server": 1,
                                        "_id": 0
                                    })

        if stream_obj["pipeline_server"] is not None:

            pipeline = yield motor.Op(
                self.db.servers.find_one,
                {"_id": ObjectId(stream_obj["pipeline_server"])}, {
                    "local_ip": 1,
                    "port": 1,
                    "_id": 0
                })

            post_args = {"stream": stream_id, "group": group_id}

            pr = PipelineRouter(self.db, None)
            url = pr.get_playlist_update_url(pipeline)

            yield tornado.gen.Task(pr.request, url=url, post_args=post_args)

        self.write({"msg": "Successfully saved"})
        self.finish()
Example #7
0
    def save(self, tags, file, original_filename, size, processed_filepath,
             user_id, stream_id, original_file_size, title, artist, group_id,
             quality, original_file):

        # Save file to database
        fs = gridfs.GridFS(self.db)
        file_id = fs.put(file)

        # Format tags in order to database can consume
        tags_db = {}
        for k, v in tags.items():
            if type(v) == gst.Buffer:
                tags_db[unicode(k)] = {}
                try:
                    tags_db[unicode(k)]["data"] = make_thumb(v)
                except:
                    pass
            elif isinstance(v, basestring) or isinstance(v, int) or isinstance(
                    v, float) or isinstance(v, long):
                tags_db[unicode(k)] = v

        if "artist" in tags_db:
            artist = self.__get_most_valid([artist, tags_db["artist"]])
        else:
            artist = self.__get_most_valid([artist])

        if "title" in tags_db:
            title = self.__get_most_valid([title, tags_db["title"]])
        else:
            title = self.__get_most_valid([title])

        if "album" in tags_db:
            album = self.__get_most_valid([tags_db["album"]])
        else:
            album = "Unknown"

        # Insert structure to database, which contains the metatags
        # constructed from tags and available informations about file

        if "weight" in original_file:
            weight = original_file["weight"]
        else:
            weight = self.__get_id()

        file = {
            "user_id": user_id,
            "original_filename": original_filename,
            "file_id": unicode(file_id),
            "size": size,
            "tags": tags_db,
            "title": title,
            "artist": artist,
            "album": album,
            "stream_id": stream_id,
            "played": 0,
            "random": random.uniform(0, 1),
            "quality": quality,
            "created_at": datetime.datetime.utcnow(),
            "groups": [{
                "id": group_id,
                "weight": weight
            }]
        }
        # groups = [
        #   {"id": ObjectId(), "weight": X}
        # ]
        self.db.media.insert(file)

        # Update limits to user
        self.db.users.update({"_id": ObjectId(user_id)},
                             {"$inc": {
                                 "size": size - original_file_size
                             }},
                             upsert=False,
                             multi=False)
        self.db.streams.update(
            {"_id": ObjectId(stream_id)},
            {"$inc": {
                "count": 1,
                "size": size - original_file_size
            }},
            upsert=False,
            multi=False)

        stream_obj = self.db.streams.find_one({"_id": ObjectId(stream_id)}, {
            "status": 1,
            "pipeline_server": 1,
            "_id": 0
        },
                                              upsert=False,
                                              multi=False)
        # print unicode(stream_obj)
        if stream_obj["status"] is None:
            self.db.streams.update({"_id": ObjectId(stream_id)},
                                   {"$set": {
                                       "status": "ready"
                                   }},
                                   upsert=False,
                                   multi=False)

        if stream_obj["pipeline_server"] is not None:
            # SEND TO PIPE UPDATE PLAYLIST
            pipeline = self.db.servers.find_one(
                {"_id": ObjectId(stream_obj["pipeline_server"])}, {
                    "local_ip": 1,
                    "port": 1,
                    "_id": 0
                },
                upsert=False,
                multi=False)

            post_args = {"stream": stream_id, "group": group_id}

            pr = PipelineRouter(self.db, None)
            url = pr.get_playlist_update_url(pipeline)

            pr.request_sync(url, post_args)

        # Remove processed temp file, because we no longer need it
        try:
            os.remove(processed_filepath)
        except OSError:
            pass
Example #8
0
    def get(self):

        stream = yield motor.Op(
            self.db.streams.find_one,
            {"_id": ObjectId(self.get_argument("streamId"))}, {
                "name": 1,
                "description": 1,
                "genres": 1,
                "status": 1,
                "public": 1,
                "cover_image": 1,
                "picture": 1,
                "user_id": 1,
                "pipeline_server": 1,
                "quality": 1,
                "reencoding": 1,
                "users": 1,
                "_id": 0
            })

        if stream is None:
            raise tornado.web.HTTPError(500)

        if stream["user_id"] == self.get_current_user():
            stream["password"] = stream["users"][0]["password"]
        del stream["users"]

        user = yield motor.Op(self.db.users.find_one,
                              {"_id": ObjectId(stream["user_id"])}, {
                                  "name": 1,
                                  "email": 1,
                                  "picture": 1,
                                  "site": 1,
                                  "country": 1,
                                  "_id": 1
                              })

        del stream["user_id"]
        user["id"] = unicode(user["_id"])
        del user["_id"]

        final_response = {}
        final_response["user"] = user
        final_response["stream"] = stream

        if stream["status"] == "ready":

            pipeline = yield motor.Op(self.db.servers.find_one, {
                "type": "pipeline",
                "level": {
                    "$lte": 9
                },
                "down": False
            }, {
                "local_ip": 1,
                "port": 1
            },
                                      sort=[('level', -1)])

            if pipeline is None:
                final_response["error"] = "Not enough Pipeline servers"
                self.write(final_response)
                self.finish()
            else:
                post_args = {"stream": self.get_argument("streamId")}
                if stream["reencoding"]:
                    post_args["quality"] = self.get_argument("quality", None)
                if "quality" not in post_args:
                    post_args["quality"] = min(stream['quality'])
                if post_args["quality"] is None:
                    post_args["quality"] = min(stream['quality'])

                pr = PipelineRouter(self.db,
                                    unicode(self.get_argument("streamId")))
                url = pr.get_start_streaming_url(pipeline)

                response = yield tornado.gen.Task(pr.request,
                                                  url=url,
                                                  post_args=post_args)

                # try again
                if "error" in response:

                    if not (response["error"] == 'No such stream'
                            and not stream['reencoding']):
                        # mark server as down
                        response = yield motor.Op(self.db.servers.update,
                                                  {"_id": pipeline["_id"]},
                                                  {"$set": {
                                                      "down": True
                                                  }},
                                                  upsert=False,
                                                  multi=False)

                    # try again with different server
                    pipeline = yield motor.Op(self.db.servers.find_one, {
                        "type": "pipeline",
                        "level": {
                            "$lte": 9
                        },
                        "down": False
                    }, {
                        "local_ip": 1,
                        "port": 1
                    },
                                              sort=[('level', -1)])

                if pipeline is None:
                    final_response["error"] = "Not enough Pipeline servers"
                    self.write(final_response)
                    self.finish()
                else:

                    if "error" in response:
                        response = yield tornado.gen.Task(pr.request,
                                                          url=url,
                                                          post_args=post_args)

                    final_response = dict(final_response.items() +
                                          response.items())

                    self.write(final_response)
                    self.finish()

        elif stream["status"] == "steady" or stream["status"] == "playing":

            query = {
                "type": "streaming",
                "streaming.streaming": True,
                "level": {
                    "$lte": 9
                },
                "down": False,
                "streaming.stream": self.get_argument("streamId")
            }
            if stream["reencoding"]:
                # print "QUALUTY "+unicode(float(self.get_argument("quality")))
                query["streaming.quality"] = self.get_argument("quality", None)

                if query["streaming.quality"] is None:
                    query["streaming.quality"] = min(stream['quality'])

            streaming_server = yield motor.Op(self.db.servers.find_one,
                                              query, {
                                                  "public_ip": 1,
                                                  "port": 1,
                                                  "streaming.mount": 1
                                              },
                                              sort=[('level', -1)])

            if streaming_server is None:

                pipeline = yield motor.Op(
                    self.db.servers.find_one,
                    {"_id": ObjectId(stream["pipeline_server"])}, {
                        "local_ip": 1,
                        "port": 1,
                        "_id": 0
                    })

                post_args = {"stream": self.get_argument("streamId")}
                if stream["reencoding"]:
                    post_args["quality"] = self.get_argument("quality", None)
                if "quality" not in post_args:
                    post_args["quality"] = min(stream['quality'])
                if post_args["quality"] is None:
                    post_args["quality"] = min(stream['quality'])

                pr = PipelineRouter(self.db,
                                    unicode(self.get_argument("streamId")))
                url = pr.get_scale_url(pipeline)

                response = yield tornado.gen.Task(pr.request,
                                                  url=url,
                                                  post_args=post_args,
                                                  raw_result=True)

                if self.is_error(response):
                    yield motor.Op(
                        self.db.streams.update,
                        {"_id": ObjectId(self.get_argument("streamId"))},
                        {"$set": {
                            "status": "ready"
                        }},
                        multi=True)

                    yield motor.Op(
                        self.db.servers.update, {
                            "streaming.stream":
                            (self.get_argument("streamId")),
                            "streaming.streaming": True
                        }, {"$set": {
                            "streaming.streaming": False
                        }},
                        multi=True)

                    #TODO
                    yield motor.Op(
                        self.db.servers.update,
                        {"_id": ObjectId(stream["pipeline_server"])},
                        {"$set": {
                            "down": True
                        }},
                        upsert=False,
                        multi=False)

                reset_state = False
                try:
                    if response.error:
                        response = {
                            "error": "Error while connecting to backend"
                        }
                    else:
                        response = json.loads(unicode(response.body))
                        if "error" in response and response[
                                "error"] == "No such stream":
                            reset_state = True
                except:
                    response = {
                        "error": "Error while parsing response from backend"
                    }

                if reset_state:
                    yield motor.Op(
                        self.db.streams.update,
                        {"_id": ObjectId(self.get_argument("streamId"))},
                        {"$set": {
                            "status": "ready"
                        }},
                        multi=True)

                final_response = dict(final_response.items() +
                                      response.items())

                self.write(final_response)
                self.finish()
            else:

                response = {
                    "public_ip": streaming_server["public_ip"],
                    "port": streaming_server["port"],
                    "mount": streaming_server["streaming"]["mount"],
                }
                final_response = dict(final_response.items() +
                                      response.items())

                self.write(final_response)
                self.finish()

        else:
            final_response["error"] = "Unknown state of stream"
            self.write(final_response)
            self.finish()