<commit_before># codplayer - player core
#
# Copyright 2013-2014 <NAME> <<EMAIL>>
#
# Distributed under an MIT license, please see LICENSE in the top dir.

"""
Classes implementing the player core.

The unit of time in all objects is one audio frame.
"""

import sys
import os
import pwd
import grp
import errno
import subprocess
import time
import threading
import Queue
import traceback
import copy

import zmq

from . import serialize
from . import db
from . import model
from . import source
from . import sink
from . import rip
from .state import State, RipState
from .command import CommandError

class PlayerError(Exception):
    pass


class Player(object):
    COMMAND_ENDPOINT = 'inproc://player-commands'

    def __init__(self, cfg, database, log_file):
        self.cfg = cfg
        self.db = database
        self.log_file = log_file
        self.log_debug = True

        self.transport = None
        
        self.ripper = None

        self.keep_running = True

        # Figure out which IDs to run as, if any
        self.uid = None
        self.gid = None

        if self.cfg.user:
            try:
                pw = pwd.getpwnam(self.cfg.user)
                self.uid = pw.pw_uid
                self.gid = pw.pw_gid
            except KeyError:
                raise PlayerError('unknown user: {0}'.format(self.cfg.user))

        if self.cfg.group:
            if not self.cfg.user:
                raise PlayerError("can't set group without user in config")
            
            try:
                gr = grp.getgrnam(self.cfg.group)
                self.gid = gr.gr_gid
            except KeyError:
                raise PlayerError('unknown group: {0}'.format(self.cfg.user))


        if self.cfg.log_performance:
            self.audio_streamer_perf_log = open('/tmp/cod_audio_streamer.log', 'wt')
        else:
            self.audio_streamer_perf_log = None
            
        
    def run(self):
        try:
            # Prepare for in-process commands
            self.zmq_context = zmq.Context()

            self.command_socket = self.zmq_context.socket(zmq.REP)
            self.command_socket.bind(self.COMMAND_ENDPOINT)

            # Kick off command servers and publishers
            commands = [c.server(self) for c in self.cfg.commands]
            self.publishers = [p.publisher(self) for p in self.cfg.publishers]

            # Drop any privs to get ready for full operation.  Do this
            # before opening the sink, since we generally need to be
            # able to reopen it with the reduced privs anyway
            if self.uid and self.gid:
                if os.geteuid() == 0:
                    try:
                        self.log('dropping privs to uid {0} gid {1}',
                                 self.uid, self.gid)

                        os.setgid(self.gid)
                        os.setuid(self.uid)
                    except OSError, e:
                        raise PlayerError("can't set UID or GID: {0}".format(e))
                else:
                    self.log('not root, not changing uid or gid')
                    
            self.transport = Transport(
                self,
                sink.SINKS[self.cfg.audio_device_type](self),
                self.publishers)

            # Force out a bunch of updates at the start to improve the
            # chance that already running state subscribers get the
            # update
            force_updates = 30

            # Main loop, executing until a quit command is received.
            # However, don't stop if a rip process is currently running.

            while self.keep_running or self.ripper is not None:
                self.run_once(1000)

                if force_updates > 0:
                    force_updates -= 1
                    self.transport.force_state_update()

        finally:
            if self.transport:
                self.transport.shutdown()
        
            # Give state and command sockets a chance to get the
            # shutdown info to the clients.
            time.sleep(1)

    #
    # Internal methods
    # 

    def run_once(self, ms_timeout):
        ev = self.command_socket.poll(ms_timeout, zmq.POLLIN)
        if ev:<commit_msg>[codplayer] Ensure correct rip state is set and announced at startup<commit_after># codplayer - player core
#
# Copyright 2013-2014 <NAME> <<EMAIL>>
#
# Distributed under an MIT license, please see LICENSE in the top dir.

"""
Classes implementing the player core.

The unit of time in all objects is one audio frame.
"""

import sys
import os
import pwd
import grp
import errno
import subprocess
import time
import threading
import Queue
import traceback
import copy

import zmq

from . import serialize
from . import db
from . import model
from . import source
from . import sink
from . import rip
from .state import State, RipState
from .command import CommandError

class PlayerError(Exception):
    pass


class Player(object):
    COMMAND_ENDPOINT = 'inproc://player-commands'

    def __init__(self, cfg, database, log_file):
        self.cfg = cfg
        self.db = database
        self.log_file = log_file
        self.log_debug = True

        self.transport = None
        
        self.ripper = None

        self.keep_running = True

        # Figure out which IDs to run as, if any
        self.uid = None
        self.gid = None

        if self.cfg.user:
            try:
                pw = pwd.getpwnam(self.cfg.user)
                self.uid = pw.pw_uid
                self.gid = pw.pw_gid
            except KeyError:
                raise PlayerError('unknown user: {0}'.format(self.cfg.user))

        if self.cfg.group:
            if not self.cfg.user:
                raise PlayerError("can't set group without user in config")
            
            try:
                gr = grp.getgrnam(self.cfg.group)
                self.gid = gr.gr_gid
            except KeyError:
                raise PlayerError('unknown group: {0}'.format(self.cfg.user))


        if self.cfg.log_performance:
            self.audio_streamer_perf_log = open('/tmp/cod_audio_streamer.log', 'wt')
        else:
            self.audio_streamer_perf_log = None
            
        
    def run(self):
        try:
            # Prepare for in-process commands
            self.zmq_context = zmq.Context()

            self.command_socket = self.zmq_context.socket(zmq.REP)
            self.command_socket.bind(self.COMMAND_ENDPOINT)

            # Kick off command servers and publishers
            commands = [c.server(self) for c in self.cfg.commands]
            self.publishers = [p.publisher(self) for p in self.cfg.publishers]

            # Drop any privs to get ready for full operation.  Do this
            # before opening the sink, since we generally need to be
            # able to reopen it with the reduced privs anyway
            if self.uid and self.gid:
                if os.geteuid() == 0:
                    try:
                        self.log('dropping privs to uid {0} gid {1}',
                                 self.uid, self.gid)

                        os.setgid(self.gid)
                        os.setuid(self.uid)
                    except OSError, e:
                        raise PlayerError("can't set UID or GID: {0}".format(e))
                else:
                    self.log('not root, not changing uid or gid')
                    
            self.transport = Transport(
                self,
                sink.SINKS[self.cfg.audio_device_type](self),
                self.publishers)

            # Force out a bunch of updates at the start to improve the
            # chance that already running state subscribers get the
            # update
            force_updates = 30

            # Main loop, executing until a quit command is received.
            # However, don't stop if a rip process is currently running.

            while self.keep_running or self.ripper is not None:
                self.run_once(1000)

                if force_updates > 0:
                    force_updates -= 1
                    self.transport.force_state_update()

                    # Also announce that we're not ripping anything (unless we are)
                    if self.ripper:
                        rip_state = self.ripper.state
                    else:
                        # Dummy inactive state
                        rip_state = RipState()

                    for p in self.publishers:
                        p.update_rip_state(rip_state)

        finally:
            if self.transport:
                self.transport.shutdown()
        
            # Give state and command sockets a chance to get the
            # shutdown info to the clients.
            time.sleep(1)

    #
    # Internal methods
    # 

    def run_once(self, ms_timeout):
        ev = self.command_socket.poll(ms_timeout, zmq.POLLIN)
        if ev:
{'fraction_non_alphanumeric': 0.07375489647453833, 'fraction_numerical': 0.0051482932288752095, 'mean_word_length': 1.5408018197327267, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4704128', 'n_tokens_mistral': 2521, 'n_tokens_neox': 2339, 'n_words': 756}