File: server.py

package info (click to toggle)
python-sfml 1.5.1.is.1.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 1,456 kB
  • ctags: 1,585
  • sloc: python: 5,747; cpp: 285; makefile: 147
file content (134 lines) | stat: -rw-r--r-- 3,703 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# pySFML - Python bindings for SFML
# Copyright 2012-2013, Jonathan De Wachter <dewachter.jonathan@gmail.com>
#
# This software is released under the LGPLv3 license.
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import threading
from time import sleep
import sfml as sf
from struct import unpack

# python 2.* compatability
try: input = raw_input
except NameError: pass

AUDIO_DATA, END_OF_STREAM = list(range(1, 3))

class NetworkAudioStream(sf.SoundStream):
	def __init__(self):
		sf.SoundStream.__init__(self)

		self.offset = 0
		self.has_finished = False
		self.listener = sf.TcpListener()
		self.samples = sf.Chunk()

		# set the sound parameters
		self.initialize(1, 44100)

	def start(self, port):
		if not self.has_finished:
			try:
				# listen to the given port for incoming connections
				self.listener.listen(port)
				print("Server is listening to port {0}, waiting for connections... ".format(port))

				# wait for a connection
				self.client = self.listener.accept()
				print("Client connected: {0}".format(self.client.remote_address))

			except sf.SocketException: return

			# start playback
			self.play()

			# start receiving audio data
			self.receive_loop()

		else:
			# start playback
			self.play()

	def on_get_data(self, chunk):
		# we have reached the end of the buffer and all audio data have been played : we can stop playback
		if self.offset >= len(self.samples) and self.has_finished:
			return False

		# no new data has arrived since last update : wait until we get some
		while self.offset >= len(self.samples) and not self.has_finished:
			sf.sleep(sf.milliseconds(10))

		# don't forget to lock as we run in two separate threads
		lock = threading.Lock()
		lock.acquire()

		# fill audio data to pass to the stream
		chunk.data = self.samples.data[self.offset*2:]

		# update the playing offset
		self.offset += len(chunk)

		lock.release()

		return True

	def on_seek(self, time_offset):
		self.offset = time_offset.milliseconds * self.sample_rate * self.channel_count // 1000

	def receive_loop(self):
		lock = threading.RLock()

		while not self.has_finished:
			# get waiting audio data from the network
			data = self.client.receive(1)

			# extract the id message
			id = unpack("B", data)[0]

			if id == AUDIO_DATA:
				# extract audio samples from the packet, and append it to our samples buffer
				data = self.client.receive(4)
				sample_count = unpack("I", data)[0]

				samples = self.client.receive(sample_count)

				# don't forget the other thread can access the sample array at any time
				lock.acquire()
				self.samples.data += samples
				lock.release()

			elif id == END_OF_STREAM:
				# end of stream reached : we stop receiving audio data
				print("Audio data has been 100% received!")
				self.has_finished = True

			else:
				# something's wrong...
				print("Invalid data received...")
				self.has_finished = True

def do_server(port):
	# build an audio stream to play sound data as it is received through the network
	audio_stream = NetworkAudioStream()
	audio_stream.start(port)

	# loop until the sound playback is finished
	while audio_stream.status != sf.SoundStream.STOPPED:
		# leave some CPU time for other threads
		sf.sleep(sf.milliseconds(100))


	# wait until the user presses 'enter' key
	input("Press enter to replay the sound...")

	# replay the sound (just to make sure replaying the received data is OK)
	audio_stream.play();

	# loop until the sound playback is finished
	while audio_stream.status != sf.SoundStream.STOPPED:
		sf.sleep(sf.milliseconds(100))