From c7e46387361f814c3599ba48c104b22b91426872 Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak Date: Wed, 2 Dec 2015 14:53:39 -0500 Subject: [PATCH 1/7] update gui to work with updated LBRYcrdWallet --- lbrynet/lbrynet_gui/LBRYGui.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lbrynet/lbrynet_gui/LBRYGui.py b/lbrynet/lbrynet_gui/LBRYGui.py index 4253cc4c4..1926d80fe 100644 --- a/lbrynet/lbrynet_gui/LBRYGui.py +++ b/lbrynet/lbrynet_gui/LBRYGui.py @@ -43,6 +43,7 @@ class LBRYDownloader(object): self.wallet_dir = os.path.join(get_path(FOLDERID.RoamingAppData, UserHandle.current), "lbrycrd") else: self.download_directory = os.getcwd() + self.wallet_dir = os.path.join(os.path.expanduser("~"), ".lbrycrd") self.wallet_conf = os.path.join(self.wallet_dir, "lbrycrd.conf") self.wallet_user = None self.wallet_password = None @@ -56,7 +57,8 @@ class LBRYDownloader(object): if os.name == "nt": self.lbrycrdd_path = "lbrycrdd.exe" else: - self.lbrycrdd_path = "./lbrycrdd" + self.lbrycrdd_path = None + self.default_lbrycrdd_path = "./lbrycrdd" self.delete_blobs_on_remove = True self.blob_request_payment_rate_manager = None @@ -122,7 +124,7 @@ class LBRYDownloader(object): if not os.path.exists(lbrycrdd_path_conf_path): return "" lbrycrdd_path_conf = open(lbrycrdd_path_conf_path) - lines = lbrycrdd_path_conf.readline() + lines = lbrycrdd_path_conf.readlines() return lines d = threads.deferToThread(get_lbrycrdd_path_conf_file) @@ -292,6 +294,8 @@ class LBRYDownloader(object): lbrycrdd_path = None if self.start_lbrycrdd is True: lbrycrdd_path = self.lbrycrdd_path + if not lbrycrdd_path: + lbrycrdd_path = self.default_lbrycrdd_path wallet = LBRYcrdWallet(self.db_dir, wallet_dir=self.wallet_dir, wallet_conf=self.wallet_conf, lbrycrdd_path=lbrycrdd_path) From 7b9479eca933dba75253956bf9de3c68030a2c4f Mon Sep 17 00:00:00 2001 From: Teran McKinney Date: Sat, 5 Dec 2015 21:25:20 +0000 Subject: [PATCH 2/7] Markdown cleanups --- INSTALL.md | 8 ++++++- README.md | 6 ++--- RUNNING.md | 70 +++++++++++++++++++++++++++++------------------------- 3 files changed, 47 insertions(+), 37 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 9776fc4b6..325ba1779 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -8,7 +8,9 @@ built into LBRYnet. on Ubuntu: +``` sudo apt-get install libgmp3-dev build-essential python-dev python-pip +``` Getting the source ------------------ @@ -20,15 +22,19 @@ Setting up the environment It's recommended that you use a virtualenv +``` sudo apt-get install python-virtualenv cd virtualenv . source bin/activate +``` (to deactivate the virtualenv, enter 'deactivate') +``` python setup.py install +``` this will install all of the libraries and a few applications -For running the file sharing application, see RUNNING +For running the file sharing application, see [RUNNING](RUNNING.md) diff --git a/README.md b/README.md index 181059fb7..45c45c46d 100644 --- a/README.md +++ b/README.md @@ -28,11 +28,11 @@ must first obtain the 'stream descriptor' and then may open it with his 'lbrynet download all of the chunks by locating peers with the chunks via the DHT, and then combine the chunks into the original file, according to the metadata included in the 'stream descriptor'. -To install and use this client, see INSTALL and RUNNING +To install and use this client, see [INSTALL](INSTALL.md) and [RUNNING](RUNNING.md) ## Installation -See INSTALL +See [INSTALL](INSTALL.md) ## Developers @@ -47,4 +47,4 @@ Send all support requests to jimmy@lbry.io ## License -See LICENSE +See [LICENSE](LICENSE.md) diff --git a/RUNNING.md b/RUNNING.md index e2a975236..1d839bc9e 100644 --- a/RUNNING.md +++ b/RUNNING.md @@ -8,59 +8,55 @@ Download the file https://raw.githubusercontent.com/lbryio/lbry-setup/master/lbr Once it's done building, type: +``` ./lbrycrd/src/lbrycrdd -server -daemon - lbrynet-gui +``` A window should show up with an entry box Type wonderfullife into the box, hit go, and choose to stream or save -To stop lbrycrdd: +To stop lbrycrdd: `./lbrycrd/src/lbrycrd-cli stop` -./lbrycrd/src/lbrycrd-cli stop ## Slightly longer install guide ### Installing lbrycrd from source -Acquire the LBRYcrd source code from https://github.com/lbryio/lbrycrd - +``` +git clone --depth=1 https://github.com/lbryio/lbrycrd.git cd lbrycrd - sudo apt-get install build-essential libtool autotools-dev autoconf pkg-config libssl-dev libboost-all-dev libdb-dev libdb++-dev libqt4-dev libprotobuf-dev protobuf-compiler - ./autogen.sh - -./configure --with-incompatible-bdb +./configure --with-incompatible-bdb --without-gui make +``` When make has completed, create the directory where LBRYcrd data will be stored. ~/.lbrycrd is where LBRYcrd will look by default and so is recommended. +``` mkdir ~/.lbrycrd - -vim ~/.lbrycrd/lbrycrd.conf - -Add the following lines to enable the RPC interface, which will be used by lbrynet-console. - -rpcuser=rpcuser - -rpcpassword=rpcpassword - -(use a long random password if your computer is on a network anyone else has access to) - +echo 'rpcuser=rpcuser +rpcpassword=rpcpassword' > ~/.lbrycrd/lbrycrd.conf +# (use a long random password if your computer is on a network anyone else has access to. e.g, pwgen -s 20) cd .. +``` + ### Installing lbrynet from source Acquire the LBRYnet source code from https://github.com/lbryio/lbry +``` cd lbry sudo apt-get install libgmp3-dev build-essential python-dev python-pip +``` (with virtualenv) +``` python-virtualenv virtualenv . @@ -69,33 +65,45 @@ source bin/activate python setup.py install +``` + to deactivate the virtualenv later: +``` deactivate +``` to reactivate it, go to the directory in which you created it and: +``` source bin/activate +``` (without virtualenv) +``` python setup.py build bdist_egg sudo python setup.py install +``` ## Slightly longer running guide -In order to use lbrynet-console or lbrynet-gui, lbyrcrdd must be running. +###In order to use lbrynet-console or lbrynet-gui, lbyrcrd must be running. ### Running lbrycrd If you ran the easy install script, the lbrycrd folder will be in the directory you ran lbry_setup.sh from. Otherwise it is the root of the cloned lbrycrd repository. Go to that directory. +``` ./src/lbrycrdd -server -daemon +``` If you want to mine LBC, also use the flag '-gen', so: +``` ./src/lbrycrdd -server -daemon -gen +``` It will take a few minutes for your client to download the whole block chain. @@ -103,35 +111,31 @@ lbrycrdd must be running in order for lbrynet to function. To shut lbrycrdd down: from the lbrycrd directory, run - ./src/lbrycrd-cli stop +``` +./src/lbrycrd-cli stop +``` ### Option 1) Running lbrynet-console If you used the virtualenv instructions above, make sure the virtualenv is still active. If not, reactivate it according to the instructions above, under "Installing lbrynet from source" -In your terminal: - -lbrynet-console +In your terminal: `lbrynet-console` You should be presented with a prompt. Watch It's a Wonderful Life via LBRY -Type into the prompt: +Type into the prompt: `get wonderfullife` -get wonderfullife - -To shut it down, type ctrl-c at any time or enter 'exit' into the prompt. +To shut it down, press ctrl-c at any time or enter `exit` into the prompt. ### Option 2) Running lbrynet-gui If you used the virtualenv instructions above, make sure the virtualenv is still active. If not, reactivate it according to the instructions above, under "Installing lbrynet from source" -In your terminal: +In your terminal: `lbrynet-gui` -lbrynet-gui - -A window should pop up with an entry box. Type 'wonderfullife' into the box, hit go, and then choose to save it or stream it. +A window should pop up with an entry box. Type `wonderfullife` into the box, hit go, and then choose to save it or stream it. Enjoy! Any questions or problems, email jimmy@lbry.io From 8195cedcf41948b04a72261e3b743a5b61efdec0 Mon Sep 17 00:00:00 2001 From: Teran McKinney Date: Sun, 6 Dec 2015 19:36:41 +0000 Subject: [PATCH 3/7] Fix LICENSE link I broke it, oops. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 45c45c46d..d9f7cd98e 100644 --- a/README.md +++ b/README.md @@ -47,4 +47,4 @@ Send all support requests to jimmy@lbry.io ## License -See [LICENSE](LICENSE.md) +See [LICENSE](LICENSE) From 654585aa6887c1f6cbac1490f5dd39810628099b Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak Date: Mon, 7 Dec 2015 00:51:40 -0500 Subject: [PATCH 4/7] require version of requests that supports json parameter --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 03a076268..c4fea7d50 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ from setuptools import setup, find_packages setup(name='lbrynet', version='0.0.4', packages=find_packages(), - install_requires=['pycrypto', 'twisted', 'miniupnpc', 'yapsy', 'seccure', 'python-bitcoinrpc==0.1', 'txJSON-RPC', 'requests', 'unqlite', 'leveldb'], + install_requires=['pycrypto', 'twisted', 'miniupnpc', 'yapsy', 'seccure', 'python-bitcoinrpc==0.1', 'txJSON-RPC', 'requests>=2.4.2', 'unqlite', 'leveldb'], entry_points={ 'console_scripts': [ 'lbrynet-console = lbrynet.lbrynet_console.LBRYConsole:launch_lbry_console', From 49ed31c895b6849fdaf38f6f8e1bbef3335298f3 Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak Date: Mon, 7 Dec 2015 15:54:51 -0500 Subject: [PATCH 5/7] stop showing options, show estimated cost --- lbrynet/lbrynet_gui/LBRYGui.py | 2 +- lbrynet/lbrynet_gui/StreamFrame.py | 91 +++++++++++++++++------------- 2 files changed, 53 insertions(+), 40 deletions(-) diff --git a/lbrynet/lbrynet_gui/LBRYGui.py b/lbrynet/lbrynet_gui/LBRYGui.py index 1926d80fe..d708ed45a 100644 --- a/lbrynet/lbrynet_gui/LBRYGui.py +++ b/lbrynet/lbrynet_gui/LBRYGui.py @@ -437,7 +437,7 @@ class LBRYDownloader(object): else: estimated_cost = "unknown" - stream_frame.show_stream_metadata(stream_name, stream_size) + stream_frame.show_stream_metadata(stream_name, stream_size, estimated_cost) available_options = metadata.options.get_downloader_options(metadata.validator, payment_rate_manager) diff --git a/lbrynet/lbrynet_gui/StreamFrame.py b/lbrynet/lbrynet_gui/StreamFrame.py index 785fb8cec..124b38cfa 100644 --- a/lbrynet/lbrynet_gui/StreamFrame.py +++ b/lbrynet/lbrynet_gui/StreamFrame.py @@ -69,36 +69,37 @@ class StreamFrame(object): self.outer_button_frame = ttk.Frame(self.stream_frame_body, style="D.TFrame") self.outer_button_frame.grid(sticky=tk.W + tk.E, row=4) - show_options_picture_file_name = "show_options.gif" - if os.name == "nt": - show_options_picture_file = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), - "lbrynet", "lbrynet_downloader_gui", - show_options_picture_file_name) - else: - show_options_picture_file = os.path.join(os.path.dirname(__file__), - show_options_picture_file_name) + #show_options_picture_file_name = "show_options.gif" + #if os.name == "nt": + # show_options_picture_file = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), + # "lbrynet", "lbrynet_downloader_gui", + # show_options_picture_file_name) + #else: + # show_options_picture_file = os.path.join(os.path.dirname(__file__), + # show_options_picture_file_name) - self.show_options_picture = tk.PhotoImage( - file=show_options_picture_file - ) + #self.show_options_picture = tk.PhotoImage( + # file=show_options_picture_file + #) - hide_options_picture_file_name = "hide_options.gif" - if os.name == "nt": - hide_options_picture_file = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), - "lbrynet", "lbrynet_downloader_gui", - hide_options_picture_file_name) - else: - hide_options_picture_file = os.path.join(os.path.dirname(__file__), - hide_options_picture_file_name) + #hide_options_picture_file_name = "hide_options.gif" + #if os.name == "nt": + # hide_options_picture_file = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), + # "lbrynet", "lbrynet_downloader_gui", + # hide_options_picture_file_name) + #else: + # hide_options_picture_file = os.path.join(os.path.dirname(__file__), + # hide_options_picture_file_name) - self.hide_options_picture = tk.PhotoImage( - file=hide_options_picture_file - ) + #self.hide_options_picture = tk.PhotoImage( + # file=hide_options_picture_file + #) - self.show_options_button = None + #self.show_options_button = None self.status_label = None self.name_label = None + self.estimated_cost_frame = None self.bytes_downloaded_label = None self.button_frame = None self.download_buttons = [] @@ -166,7 +167,7 @@ class StreamFrame(object): return "%.1f %s" % (round((stream_size * 1.0 / factor), 1), units) return stream_size - def show_stream_metadata(self, stream_name, stream_size): + def show_stream_metadata(self, stream_name, stream_size, stream_cost): if self.status_label is not None: self.status_label.destroy() @@ -186,6 +187,17 @@ class StreamFrame(object): ) file_name_label.grid(row=0, column=3) + self.estimated_cost_frame = ttk.Frame(self.metadata_frame, style="F.TFrame") + self.estimated_cost_frame.grid(row=1, column=0, sticky=tk.W) + + estimated_cost_label = ttk.Label( + self.estimated_cost_frame, + text=locale.format_string("%.2f LBC", + (round(stream_cost, 2)), grouping=True), + foreground="red" + ) + estimated_cost_label.grid(row=1, column=2) + self.button_frame = ttk.Frame(self.outer_button_frame, style="E.TFrame") self.button_frame.grid(row=0, column=1) @@ -309,12 +321,12 @@ class StreamFrame(object): option_widget = self.get_option_widget(option.option_types[0], choice_frame) option_widget.grid(row=0, column=0, sticky=tk.W) f.option_widget = option_widget - self.show_options_button = ttk.Button( - self.stream_frame_body, command=self._toggle_show_options, style="Stop.TButton", - cursor=self.button_cursor - ) - self.show_options_button.config(image=self.show_options_picture) - self.show_options_button.grid(sticky=tk.W, row=2, column=0) + #self.show_options_button = ttk.Button( + # self.stream_frame_body, command=self._toggle_show_options, style="Stop.TButton", + # cursor=self.button_cursor + #) + #self.show_options_button.config(image=self.show_options_picture) + #self.show_options_button.grid(sticky=tk.W, row=2, column=0) def _get_chosen_option(self, option_type, option_widget): if option_type.value == float: @@ -337,23 +349,24 @@ class StreamFrame(object): chosen_options.append(self._get_chosen_option(option_type, option_widget)) return chosen_options - def _toggle_show_options(self): - if self.options_frame.winfo_ismapped(): - self.show_options_button.config(image=self.show_options_picture) - self.options_frame.grid_forget() - else: - self.show_options_button.config(image=self.hide_options_picture) - self.options_frame.grid(sticky=tk.W + tk.E, row=3) + #def _toggle_show_options(self): + # if self.options_frame.winfo_ismapped(): + # self.show_options_button.config(image=self.show_options_picture) + # self.options_frame.grid_forget() + # else: + # self.show_options_button.config(image=self.hide_options_picture) + # self.options_frame.grid(sticky=tk.W + tk.E, row=3) def show_progress(self, total_bytes, bytes_left_to_download, points_paid, points_remaining): if self.bytes_downloaded_label is None: self.remove_download_buttons() self.button_frame.destroy() + self.estimated_cost_frame.destroy() for option, frame in self.option_frames: frame.destroy() self.options_frame.destroy() - self.show_options_button.destroy() + #self.show_options_button.destroy() self.progress_frame = ttk.Frame(self.outer_button_frame, style="F.TFrame") self.progress_frame.grid(row=0, column=0, sticky=tk.W, pady=(0, 8)) @@ -365,7 +378,7 @@ class StreamFrame(object): self.bytes_downloaded_label.grid(row=0, column=0) self.cost_frame = ttk.Frame(self.outer_button_frame, style="F.TFrame") - self.cost_frame.grid(row=1, column=0, sticky=tk.W, pady=(0, 7)) + self.cost_frame.grid(row=1, column=0, sticky=tk.W, pady=(0, 4)) self.cost_label = ttk.Label( self.cost_frame, From 636692ba6aabaaa594748418284c2bd7d1689187 Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak Date: Wed, 9 Dec 2015 02:33:50 -0500 Subject: [PATCH 6/7] show a thumbnail if one is included in the blockchain --- lbrynet/lbrynet_gui/LBRYGui.py | 2 + lbrynet/lbrynet_gui/StreamFrame.py | 79 +++++++++++++++++++++++++----- 2 files changed, 68 insertions(+), 13 deletions(-) diff --git a/lbrynet/lbrynet_gui/LBRYGui.py b/lbrynet/lbrynet_gui/LBRYGui.py index d708ed45a..610f58c4a 100644 --- a/lbrynet/lbrynet_gui/LBRYGui.py +++ b/lbrynet/lbrynet_gui/LBRYGui.py @@ -397,6 +397,8 @@ class LBRYDownloader(object): stream_frame.show_name(value['name']) if 'description' in value: stream_frame.show_description(value['description']) + if 'thumbnail' in value: + stream_frame.show_thumbnail(value['thumbnail']) return value def get_sd_hash(value): diff --git a/lbrynet/lbrynet_gui/StreamFrame.py b/lbrynet/lbrynet_gui/StreamFrame.py index 124b38cfa..5f071e1a5 100644 --- a/lbrynet/lbrynet_gui/StreamFrame.py +++ b/lbrynet/lbrynet_gui/StreamFrame.py @@ -56,7 +56,8 @@ class StreamFrame(object): self.name_frame = ttk.Frame(self.stream_frame_body, style="D.TFrame") self.name_frame.grid(sticky=tk.W + tk.E) - self.name_frame.grid_columnconfigure(0, weight=1) + self.name_frame.grid_columnconfigure(0, weight=16) + self.name_frame.grid_columnconfigure(1, weight=1) self.stream_frame_body.grid_columnconfigure(0, weight=1) @@ -98,14 +99,16 @@ class StreamFrame(object): #self.show_options_button = None self.status_label = None - self.name_label = None + #self.name_label = None + self.name_text = None self.estimated_cost_frame = None self.bytes_downloaded_label = None self.button_frame = None self.download_buttons = [] self.option_frames = [] self.name_font = None - self.description_label = None + self.description_text = None + #self.description_label = None self.file_name_frame = None self.cost_frame = None self.cost_description = None @@ -120,22 +123,72 @@ class StreamFrame(object): self.stream_frame.destroy() self.app.stream_removed() + def _resize_text(self, text_widget): + actual_height = text_widget.tk.call(text_widget._w, "count", "-displaylines", "0.0", "end") + text_widget.config(height=int(actual_height)) + def show_name(self, name): self.name_font = tkFont.Font(size=16) - self.name_label = ttk.Label( - self.name_frame, text=name, font=self.name_font + #self.name_label = ttk.Label( + # self.name_frame, text=name, font=self.name_font + #) + #self.name_label.grid(row=0, column=0, sticky=tk.W) + self.name_text = tk.Text( + self.name_frame, font=self.name_font, wrap=tk.WORD, relief=tk.FLAT, borderwidth=0, + highlightthickness=0, width=1, height=1 ) - self.name_label.grid(row=0, column=0, sticky=tk.W) + self.name_text.insert(tk.INSERT, name) + self.name_text.config(state=tk.DISABLED) + self.name_text.grid(row=0, column=0, sticky=tk.W+tk.E+tk.N+tk.S) + self.name_text.update() + self._resize_text(self.name_text) def show_description(self, description): - if os.name == "nt": - wraplength = 580 - else: - wraplength = 600 - self.description_label = ttk.Label( - self.name_frame, text=description, wraplength=wraplength + #if os.name == "nt": + # wraplength = 580 + #else: + # wraplength = 600 + #self.description_label = ttk.Label( + # self.name_frame, text=description, wraplength=wraplength + #) + #self.description_label.grid(row=1, column=0, sticky=tk.W) + self.description_text = tk.Text( + self.name_frame, wrap=tk.WORD, relief=tk.FLAT, borderwidth=0, + highlightthickness=0, width=1, height=1 ) - self.description_label.grid(row=1, column=0, sticky=tk.W) + self.description_text.insert(tk.INSERT, description) + self.description_text.config(state=tk.DISABLED) + self.description_text.grid(row=1, column=0, sticky=tk.W+tk.E+tk.N+tk.S) + self.description_text.update() + self._resize_text(self.description_text) + + def show_thumbnail(self, url=None): + thumbnail = None + if url is not None: + import urllib2 + import base64 + response = urllib2.urlopen(url) + thumbnail_data = base64.b64encode(response.read()) + thumbnail = tk.PhotoImage(data=thumbnail_data) + current_width = thumbnail.width() + current_height = thumbnail.height() + max_width = 130 + max_height = 90 + scale_ratio = max(1.0 * current_width / max_width, 1.0 * current_height / max_height) + if scale_ratio < 1: + scale_ratio = 1 + else: + scale_ratio = int(scale_ratio + 1) + thumbnail = thumbnail.subsample(scale_ratio) + if thumbnail is not None: + label = ttk.Label(self.name_frame, image=thumbnail) + label.safekeeping = thumbnail + label.grid(row=0, column=1, rowspan=2, sticky=tk.E+tk.N+tk.W+tk.S) + label.update() + self.description_text.update() + self.name_text.update() + self._resize_text(self.description_text) + self._resize_text(self.name_text) def show_metadata_status(self, value): if self.status_label is None: From ce1c28ffb9a62b0dfe2f9da7219950e811690079 Mon Sep 17 00:00:00 2001 From: Jimmy Kiselak Date: Thu, 10 Dec 2015 00:37:43 -0500 Subject: [PATCH 7/7] allow the thumbnail link to get to the gui --- lbrynet/core/LBRYcrdWallet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lbrynet/core/LBRYcrdWallet.py b/lbrynet/core/LBRYcrdWallet.py index 476457391..5327cb6f0 100644 --- a/lbrynet/core/LBRYcrdWallet.py +++ b/lbrynet/core/LBRYcrdWallet.py @@ -275,7 +275,7 @@ class LBRYcrdWallet(object): value_dict = json.loads(value) except ValueError: return Failure(InvalidStreamInfoError(name)) - known_fields = ['stream_hash', 'name', 'description', 'key_fee', 'key_fee_address'] + known_fields = ['stream_hash', 'name', 'description', 'key_fee', 'key_fee_address', 'thumbnail'] for field in known_fields: if field in value_dict: r_dict[field] = value_dict[field]